Просмотр исходного кода

Merge branch 'findchan_by_dname_hash'

* findchan_by_dname_hash: (24 commits)
  Eliminate use of slow HashTable.each
  Don't insert on lookup.
  Use range for loops in some places
  Update bdlib
  This can now use fast findchan_by_dname()
  This wrapper isn't needed
  Convert some things to STL where easily possible.
  Remove unused function conf_getlocalhub
  Update bdlib
  These can be const reference
  Update bdlib
  These are noexcept
  This can be inlined
  Add some pure/const attributes
  Optimize rfc functions for common case of using them.
  Use some noexcept and pure attributes
  ismember: const reference is fine here
  Use shard_ptr for memberlist.rfc_nick
  Use new/delete for memberlist so non-pointer members can be constructed
  Store RfcString'd nick in memberlist
  ...
Bryan Drewery 7 лет назад
Родитель
Сommit
780eb80119
55 измененных файлов с 508 добавлено и 349 удалено
  1. 1 1
      lib/bdlib
  2. 3 1
      src/EncryptedStream.h
  3. 1 0
      src/Makefile.in
  4. 50 0
      src/RfcString.cc
  5. 73 0
      src/RfcString.h
  6. 65 54
      src/auth.cc
  7. 22 14
      src/auth.h
  8. 1 1
      src/base64.cc
  9. 1 1
      src/base64.h
  10. 0 0
      src/binds.cc
  11. 6 5
      src/botnet.cc
  12. 5 5
      src/botnet.h
  13. 13 0
      src/chan.h
  14. 22 39
      src/chanprog.cc
  15. 37 12
      src/chanprog.h
  16. 7 17
      src/cmds.cc
  17. 14 5
      src/cmds.h
  18. 0 14
      src/conf.cc
  19. 0 1
      src/conf.h
  20. 0 2
      src/crypt.h
  21. 4 3
      src/dcc.cc
  22. 1 1
      src/dcc.h
  23. 2 10
      src/dccutil.cc
  24. 9 3
      src/dccutil.h
  25. 2 1
      src/egg_timer.h
  26. 2 2
      src/flags.cc
  27. 13 11
      src/flags.h
  28. 1 1
      src/garble.cc
  29. 2 2
      src/log.cc
  30. 1 1
      src/log.h
  31. 7 7
      src/match.cc
  32. 3 3
      src/match.h
  33. 2 5
      src/misc.cc
  34. 3 4
      src/misc.h
  35. 2 2
      src/misc_file.cc
  36. 7 7
      src/misc_file.h
  37. 6 8
      src/mod/channels.mod/chanmisc.cc
  38. 1 0
      src/mod/channels.mod/channels.cc
  39. 11 11
      src/mod/irc.mod/chan.cc
  40. 4 5
      src/mod/irc.mod/irc.cc
  41. 1 1
      src/mod/server.mod/servmsg.cc
  42. 3 9
      src/net.cc
  43. 13 8
      src/net.h
  44. 2 1
      src/response.h
  45. 7 47
      src/rfc1459.cc
  46. 58 6
      src/rfc1459.h
  47. 4 2
      src/set.cc
  48. 1 1
      src/set.h
  49. 2 2
      src/shell.cc
  50. 5 5
      src/shell.h
  51. 1 1
      src/socket.cc
  52. 1 1
      src/socket.h
  53. 2 2
      src/tandem.h
  54. 1 1
      src/userent.cc
  55. 3 3
      src/users.h

+ 1 - 1
lib/bdlib

@@ -1 +1 @@
-Subproject commit 482345aa342e76ca3232b04c11f02b32dd867662
+Subproject commit 3f1b81af3a4b70cea90230b7f923589f2b9f5973

+ 3 - 1
src/EncryptedStream.h

@@ -34,7 +34,9 @@ class EncryptedStream : public bd::Stream {
         EncryptedStream(bd::String& keyStr) : Stream(), key(keyStr), enc_flags(ENC_DEFAULT) {};
         EncryptedStream(bd::String& keyStr) : Stream(), key(keyStr), enc_flags(ENC_DEFAULT) {};
         EncryptedStream(EncryptedStream& stream) : Stream(stream), key(stream.key), enc_flags(ENC_DEFAULT) {};
         EncryptedStream(EncryptedStream& stream) : Stream(stream), key(stream.key), enc_flags(ENC_DEFAULT) {};
 
 
-        void setFlags(const char _enc_flags) const { enc_flags = _enc_flags; }
+        inline void setFlags(const char _enc_flags) const noexcept {
+          enc_flags = _enc_flags;
+        }
         virtual int loadFile(const int fd);
         virtual int loadFile(const int fd);
         using bd::Stream::loadFile;
         using bd::Stream::loadFile;
 
 

+ 1 - 0
src/Makefile.in

@@ -55,6 +55,7 @@ OBJS = auth.So \
 	adns.So \
 	adns.So \
 	response.So \
 	response.So \
 	rfc1459.So \
 	rfc1459.So \
+	RfcString.o \
 	set.So \
 	set.So \
 	shell.So \
 	shell.So \
 	socket.So \
 	socket.So \

+ 50 - 0
src/RfcString.cc

@@ -0,0 +1,50 @@
+/* RfcString.cc
+ *
+ */
+#include <stdlib.h>
+#include "RfcString.h"
+
+int
+RfcString::compare(const RfcString& str, size_t n) const noexcept
+{
+  if (rfc_casecmp != _rfc_casecmp)
+    return String::compare(str, n);
+  /* Same string? */
+  if (cbegin() == str.cbegin() && length() == str.length())
+    return 0;
+  if (n == npos)
+    n = std::max(length(), str.length());
+  auto s1 = cbegin();
+  auto s2 = str.cbegin();
+  /* XXX: std::lexicographical_compare_3way would be nice ... */
+  int cmp = 0;
+  while (n > 0 && s1 != cend() && s2 != str.cend()) {
+    if ((cmp = _rfc_toupper(*s1) - _rfc_toupper(*s2)) != 0)
+      return cmp;
+    ++s1;
+    ++s2;
+    --n;
+  }
+  if (n == 0)
+    return 0;
+  else if (s1 != cend())
+    return 1;
+  else if (s2 != str.cend())
+    return -1;
+  else
+    return 0;
+  return _rfc_toupper(*s1) - _rfc_toupper(*s2);
+}
+
+size_t
+RfcString::hash() const noexcept {
+  if (my_hash != 0) return my_hash;
+  if (rfc_casecmp != _rfc_casecmp)
+    return String::hash();
+  std::hash<value_type> hasher;
+  size_t _hash = 5381;
+
+  for(size_t i = 0; i < this->length(); ++i)
+    _hash = ((_hash << 5) + _hash) + hasher(_rfc_toupper(this->data()[i]));
+  return (my_hash = (_hash & 0x7FFFFFFF));
+}

+ 73 - 0
src/RfcString.h

@@ -0,0 +1,73 @@
+#ifndef _RFCSTRING_H
+#define _RFCSTRING_H 1
+
+namespace bd {
+  class String;
+}
+#include "rfc1459.h"
+#include <bdlib/src/String.h>
+
+class RfcString : public bd::String {
+  private:
+
+  protected:
+
+  public:
+    using String::String;
+    RfcString(const String &str) : String(str) {};
+    RfcString(String &&str) : String(std::move(str)) {};
+
+    int compare(const RfcString& str, size_t n = npos) const noexcept
+      __attribute__((pure));
+    friend bool operator==(const RfcString&, const RfcString&);
+    friend bool operator!=(const RfcString&, const RfcString&);
+    friend bool operator<(const RfcString&, const RfcString&);
+    friend bool operator<=(const RfcString&, const RfcString&);
+    friend bool operator>(const RfcString&, const RfcString&);
+    friend bool operator>=(const RfcString&, const RfcString&);
+
+    virtual size_t hash() const noexcept;
+};
+
+inline bool __attribute__((pure))
+operator==(const RfcString& lhs, const RfcString& rhs) {
+  return (lhs.length() == rhs.length() &&
+      lhs.compare(rhs) == 0);
+}
+
+inline bool __attribute__((pure))
+operator!=(const RfcString& lhs, const RfcString& rhs) {
+  return ! (lhs == rhs);
+}
+
+inline bool __attribute__((pure))
+operator<(const RfcString& lhs, const RfcString& rhs) {
+  return (lhs.compare(rhs) < 0);
+}
+
+inline bool __attribute__((pure))
+operator<=(const RfcString& lhs, const RfcString& rhs) {
+  return ! (rhs < lhs);
+}
+
+inline bool __attribute__((pure))
+operator>(const RfcString& lhs, const RfcString& rhs) {
+  return (rhs < lhs);
+}
+
+inline bool __attribute__((pure))
+operator>=(const RfcString& lhs, const RfcString& rhs) {
+  return ! (lhs < rhs);
+}
+
+namespace std {
+  template<>
+  struct hash<RfcString>
+    {
+          inline size_t operator()(const RfcString& val) const {
+            return val.hash();
+          }
+    };
+}
+
+#endif

+ 65 - 54
src/auth.cc

@@ -65,28 +65,29 @@ Auth::~Auth()
   ht_nick.remove(nick);
   ht_nick.remove(nick);
 }
 }
 
 
-void Auth::MakeHash()
+void Auth::MakeHash() noexcept
 {
 {
  make_rand_str(rand, 50);
  make_rand_str(rand, 50);
  makehash(user, rand, hash, 50);
  makehash(user, rand, hash, 50);
 }
 }
 
 
-void Auth::Done()
+void Auth::Done() noexcept
 {
 {
   hash[0] = 0;
   hash[0] = 0;
   rand[0] = 0;
   rand[0] = 0;
   Status(AUTHED);
   Status(AUTHED);
 }
 }
 
 
-void Auth::NewNick(const char *newnick) {
+void Auth::NewNick(const char *newnick) noexcept
+{
   if (ht_nick.contains(nick)) {
   if (ht_nick.contains(nick)) {
-    Auth::ht_nick.remove(nick);
+    ht_nick.remove(nick);
   }
   }
   strlcpy(nick, newnick, NICKLEN);
   strlcpy(nick, newnick, NICKLEN);
   ht_nick[newnick] = this;
   ht_nick[newnick] = this;
 }
 }
 
 
-Auth *Auth::Find(const char *_host)
+Auth *Auth::Find(const char *_host) noexcept
 {
 {
 
 
   if (ht_host.contains(_host)) {
   if (ht_host.contains(_host)) {
@@ -98,7 +99,7 @@ Auth *Auth::Find(const char *_host)
   return NULL;
   return NULL;
 }
 }
 
 
-static void auth_clear_users_block(const bd::String key, Auth* auth, void *param)
+static void auth_clear_users_block(const bd::String& key, Auth* auth)
 {
 {
   if (auth->user) {
   if (auth->user) {
     sdprintf(STR("Clearing USER for auth: (%s!%s) [%s]"), auth->nick,
     sdprintf(STR("Clearing USER for auth: (%s!%s) [%s]"), auth->nick,
@@ -107,19 +108,19 @@ static void auth_clear_users_block(const bd::String key, Auth* auth, void *param
   }
   }
 }
 }
 
 
-void Auth::NullUsers(const char *nick)
+void Auth::NullUsers(const char *nick) noexcept
 {
 {
   if (nick == NULL) {
   if (nick == NULL) {
-    ht_host.each(auth_clear_users_block);
-  } else {
-    if (ht_nick.contains(nick)) {
-      Auth *auth = ht_nick[nick];
-      auth_clear_users_block(nick, auth, NULL);
+    for (auto& kv : ht_host) {
+      auth_clear_users_block(kv.first, kv.second);
     }
     }
+  } else if (ht_nick.contains(nick)) {
+    Auth* auth = ht_nick[nick];
+    auth_clear_users_block(nick, auth);
   }
   }
 }
 }
 
 
-static void auth_fill_users_block(const bd::String key, Auth* auth, void* param)
+static void auth_fill_users_block(const bd::String& key, Auth* auth)
 {
 {
   char from[NICKLEN + UHOSTLEN];
   char from[NICKLEN + UHOSTLEN];
 
 
@@ -129,59 +130,73 @@ static void auth_fill_users_block(const bd::String key, Auth* auth, void* param)
   auth->user = get_user_by_host(from);
   auth->user = get_user_by_host(from);
 }
 }
 
 
-void Auth::FillUsers(const char *nick)
+void Auth::FillUsers(const char *nick) noexcept
 {
 {
   if (nick == NULL) {
   if (nick == NULL) {
-    ht_host.each(auth_fill_users_block);
-  } else {
-    if (ht_nick.contains(nick)) {
-      Auth *auth = ht_nick[nick];
-      auth_fill_users_block(nick, auth, NULL);
+    for (auto& kv : ht_host) {
+      auth_fill_users_block(kv.first, kv.second);
     }
     }
+  } else if (ht_nick.contains(nick)) {
+    Auth *auth = ht_nick[nick];
+    auth_fill_users_block(nick, auth);
   }
   }
 }
 }
 
 
 
 
-static void auth_expire_block(const bd::String key, Auth* auth, void* param)
+void Auth::ExpireAuths() noexcept
 {
 {
-  if (auth->Authed() && ((now - auth->atime) >= (60 * 60))) {
-    Auth::ht_host.remove(key);
-    Auth::ht_nick.remove(auth->nick);
+  if (!ischanhub() || ht_host.size() == 0)
+    return;
+  std::vector<bd::String> expired_hosts;
+  expired_hosts.reserve(ht_host.size());
+  std::vector<const Auth*> delete_auths;
+  delete_auths.reserve(ht_host.size());
+
+  for (const auto& kv : ht_host) {
+    const bd::String& host = kv.first;
+    const auto& auth = kv.second;
+    if (auth->Authed() && ((now - auth->atime) >= (60 * 60))) {
+      putlog(LOG_DEBUG, "*", STR("Auth (%s!%s) [%s] expired."),
+          auth->nick, auth->host, auth->user ? auth->user->handle : "*");
+      expired_hosts.push_back(host);
+      ht_nick.remove(auth->nick);
+      delete_auths.push_back(auth);
+    }
+  }
+  for (const auto& host : expired_hosts) {
+    ht_host.remove(host);
+  }
+  for (const auto& auth : delete_auths) {
     delete auth;
     delete auth;
   }
   }
 }
 }
 
 
-void Auth::ExpireAuths()
+void Auth::DeleteAll() noexcept
 {
 {
   if (!ischanhub())
   if (!ischanhub())
     return;
     return;
-
-  ht_host.each(auth_expire_block);
-}
-
-static void auth_delete_all_block(const bd::String, Auth* auth, void* param)
-{
-  putlog(LOG_DEBUG, "*", STR("Removing (%s!%s) [%s], from auth list."),
-      auth->nick, auth->host, auth->user ? auth->user->handle : "*");
-  delete auth;
-}
-
-void Auth::DeleteAll()
-{
-  if (ischanhub()) {
-    putlog(LOG_DEBUG, "*", STR("Removing auth entries."));
-    ht_host.each(auth_delete_all_block);
-    ht_host.clear();
-    ht_nick.clear();
+  putlog(LOG_DEBUG, "*", STR("Removing auth entries."));
+  std::vector<const Auth*> delete_auths;
+  delete_auths.reserve(ht_host.size());
+  for (const auto& kv : ht_host) {
+    const auto& auth = kv.second;
+    putlog(LOG_DEBUG, "*", STR("Removing (%s!%s) [%s], from auth list."),
+        auth->nick, auth->host, auth->user ? auth->user->handle : "*");
+    delete_auths.push_back(auth);
+  }
+  ht_host.clear();
+  ht_nick.clear();
+  for (const auto& auth : delete_auths) {
+    delete auth;
   }
   }
 }
 }
 
 
-void Auth::InitTimer()
+void Auth::InitTimer() noexcept
 {
 {
   timer_create_secs(60, STR("Auth::ExpireAuths"), (Function) Auth::ExpireAuths);
   timer_create_secs(60, STR("Auth::ExpireAuths"), (Function) Auth::ExpireAuths);
 }
 }
 
 
-bool Auth::GetIdx(const char *chname)
+bool Auth::GetIdx(const char *chname) noexcept
 {
 {
 sdprintf(STR("GETIDX: auth: %s, idx: %d"), nick, idx);
 sdprintf(STR("GETIDX: auth: %s, idx: %d"), nick, idx);
   if (idx != -1) {
   if (idx != -1) {
@@ -242,19 +257,15 @@ sdprintf(STR("GETIDX: auth: %s, idx: %d"), nick, idx);
   return 0;
   return 0;
 }
 }
 
 
-static void auth_tell_block(const bd::String key, Auth* auth, void* param)
+void Auth::TellAuthed(int idx) noexcept
 {
 {
-  long lparam = (long) param;
-  int idx = (int) lparam;
-
-  dprintf(idx, "(%s!%s) [%s] authtime: %li, atime: %li, Status: %d\n", auth->nick, 
+  for (const auto& kv : ht_host) {
+    const Auth* auth = kv.second;
+    dprintf(idx, "(%s!%s) [%s] authtime: %li, atime: %li, Status: %d\n",
+        auth->nick,
         auth->host, auth->user ? auth->user->handle : "*",
         auth->host, auth->user ? auth->user->handle : "*",
         (long)auth->authtime, (long)auth->atime, auth->Status());
         (long)auth->authtime, (long)auth->atime, auth->Status());
-}
-
-void Auth::TellAuthed(int idx)
-{
-  ht_host.each(auth_tell_block, (void *) (long) idx);
+  }
 }
 }
 
 
 void makehash(struct userrec *u, const char *randstring, char *out, size_t out_size)
 void makehash(struct userrec *u, const char *randstring, char *out, size_t out_size)

+ 22 - 14
src/auth.h

@@ -17,20 +17,28 @@ class Auth {
   Auth(const char *, const char *, struct userrec * = NULL);
   Auth(const char *, const char *, struct userrec * = NULL);
   ~Auth();
   ~Auth();
 
 
-  int Status(int newstat = -1) { if (newstat >= 0) { status = newstat; } return status; }
-  void MakeHash();
-  bool Authed() { return (status == AUTHED); }
-  bool GetIdx(const char *);
-  void Done();
-  void NewNick(const char *nick);
-
-  static Auth *Find(const char * host);
-  static void NullUsers(const char *nick = NULL);
-  static void FillUsers(const char *nick = NULL);
-  static void ExpireAuths();
-  static void InitTimer();
-  static void DeleteAll();
-  static void TellAuthed(int);
+  inline int Status(void) const noexcept __attribute__((pure)) {
+    return status;
+  }
+  int Status(int newstat) noexcept {
+    status = newstat;
+    return Status();
+  }
+  void MakeHash() noexcept;
+  bool Authed() const noexcept __attribute__((pure)) {
+    return (status == AUTHED);
+  }
+  bool GetIdx(const char *) noexcept;
+  void Done() noexcept;
+  void NewNick(const char *nick) noexcept;
+
+  static Auth *Find(const char * host) noexcept __attribute__((pure));
+  static void NullUsers(const char *nick = NULL) noexcept;
+  static void FillUsers(const char *nick = NULL) noexcept;
+  static void ExpireAuths() noexcept;
+  static void InitTimer() noexcept;
+  static void DeleteAll() noexcept;
+  static void TellAuthed(int) noexcept;
 
 
   struct userrec *user;
   struct userrec *user;
   time_t authtime;              /* what time they authed at */
   time_t authtime;              /* what time they authed at */

+ 1 - 1
src/base64.cc

@@ -54,7 +54,7 @@ static const char base64r[256] = {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 };
 };
 
 
-static char base64to[256] =
+static const char base64to[256] =
 {
 {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

+ 1 - 1
src/base64.h

@@ -7,7 +7,7 @@ namespace bd {
 };
 };
 
 
 char *int_to_base64(unsigned int);
 char *int_to_base64(unsigned int);
-int base64_to_int(const char *);
+int base64_to_int(const char *) __attribute__((pure));
 
 
 bd::String broken_base64Encode(const bd::String&);
 bd::String broken_base64Encode(const bd::String&);
 char *b64enc(const unsigned char *data, size_t len);
 char *b64enc(const unsigned char *data, size_t len);

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
src/binds.cc


+ 6 - 5
src/botnet.cc

@@ -54,6 +54,7 @@
 #include <bdlib/src/String.h>
 #include <bdlib/src/String.h>
 #include <bdlib/src/Array.h>
 #include <bdlib/src/Array.h>
 #include <algorithm>
 #include <algorithm>
+#include <unordered_map>
 
 
 tand_t			*tandbot = NULL;		/* Keep track of tandem bots on the
 tand_t			*tandbot = NULL;		/* Keep track of tandem bots on the
 							   botnet */
 							   botnet */
@@ -245,7 +246,7 @@ void partysetidle(char *bot, int sock, int secs)
 
 
 /* Return someone's chat channel.
 /* Return someone's chat channel.
  */
  */
-int getparty(char *bot, int sock)
+int getparty(const char *bot, int sock)
 {
 {
   for (int i = 0; i < parties; i++) {
   for (int i = 0; i < parties; i++) {
     if (!strcasecmp(party[i].bot, bot) &&
     if (!strcasecmp(party[i].bot, bot) &&
@@ -581,7 +582,7 @@ tell_bots(int idx, int up, const char *nodename)
 {
 {
   size_t total = 0, maxNodeNameLength = 0;;
   size_t total = 0, maxNodeNameLength = 0;;
   bd::Array<bd::String> nodes;
   bd::Array<bd::String> nodes;
-  bd::HashTable<bd::String, bd::Array<bd::String> > nodeBots;
+  std::unordered_map<bd::String, bd::Array<bd::String> > nodeBots;
   bd::Array<bd::String> bots;
   bd::Array<bd::String> bots;
   bd::String group;
   bd::String group;
 
 
@@ -852,7 +853,7 @@ void dump_links(int z)
   }
   }
 }
 }
 
 
-int in_chain(char *who)
+int in_chain(const char *who)
 {
 {
   if (!strcasecmp(who, conf.bot->nick))
   if (!strcasecmp(who, conf.bot->nick))
     return 1;
     return 1;
@@ -861,7 +862,7 @@ int in_chain(char *who)
   return 0;
   return 0;
 }
 }
 
 
-int bots_in_subtree(tand_t *bot)
+int bots_in_subtree(const tand_t *bot)
 {
 {
   if (!bot)
   if (!bot)
     return 0;
     return 0;
@@ -877,7 +878,7 @@ int bots_in_subtree(tand_t *bot)
   return nr;
   return nr;
 }
 }
 
 
-int users_in_subtree(tand_t *bot)
+int users_in_subtree(const tand_t *bot)
 {
 {
   if (!bot)
   if (!bot)
     return 0;
     return 0;

+ 5 - 5
src/botnet.h

@@ -13,9 +13,9 @@ extern int		tands;
 
 
 void lower_bot_linked(int idx);
 void lower_bot_linked(int idx);
 void answer_local_whom(int, int);
 void answer_local_whom(int, int);
-char *lastbot(const char *);
-int nextbot(const char *);
-int in_chain(char *);
+char *lastbot(const char *) __attribute__((pure));
+int nextbot(const char *) __attribute__((pure));
+int in_chain(const char *) __attribute__((pure));
 void tell_bots(int, int, const char *);
 void tell_bots(int, int, const char *);
 void tell_bottree(int);
 void tell_bottree(int);
 void dump_links(int);
 void dump_links(int);
@@ -24,7 +24,7 @@ int botunlink(int, const char *, const char *);
 void addbot(char *, char *, char *, char, int, time_t, char *, char *, int);
 void addbot(char *, char *, char *, char, int, time_t, char *, char *, int);
 void updatebot(int, char *, char, int, time_t, char *, char *, int);
 void updatebot(int, char *, char, int, time_t, char *, char *, int);
 void rembot(const char *);
 void rembot(const char *);
-tand_t *findbot(const char *);
+tand_t *findbot(const char *) __attribute__((pure));
 void unvia(int, struct tand_t_struct *);
 void unvia(int, struct tand_t_struct *);
 void check_botnet_pings();
 void check_botnet_pings();
 int addparty(char *, char *, int, char, int, char *, int *);
 int addparty(char *, char *, int, char, int, char *, int *);
@@ -37,6 +37,6 @@ void partyaway(char *, int, char *);
 void botnet_send_cmdpass(int, char *, char *);
 void botnet_send_cmdpass(int, char *, char *);
 void zapfbot(int);
 void zapfbot(int);
 void tandem_relay(int, char *, int);
 void tandem_relay(int, char *, int);
-int getparty(char *, int);
+int getparty(const char *, int) __attribute__((pure));
 void init_party(void);
 void init_party(void);
 #endif /* !_BOTNET_H */
 #endif /* !_BOTNET_H */

+ 13 - 0
src/chan.h

@@ -9,8 +9,11 @@
 #define _EGG_CHAN_H
 #define _EGG_CHAN_H
 
 
 #include <functional>
 #include <functional>
+#include <memory>
 #include <lib/bdlib/src/Array.h>
 #include <lib/bdlib/src/Array.h>
+#include <lib/bdlib/src/HashTable.h>
 #include <lib/bdlib/src/String.h>
 #include <lib/bdlib/src/String.h>
+#include "RfcString.h"
 
 
 /* chan & global */
 /* chan & global */
 enum flood_t {
 enum flood_t {
@@ -49,6 +52,7 @@ typedef struct memstruct {
   int tried_getuser;
   int tried_getuser;
   unsigned short flags;
   unsigned short flags;
   char nick[NICKLEN];
   char nick[NICKLEN];
+  std::shared_ptr<RfcString> rfc_nick;
   char userhost[UHOSTLEN];
   char userhost[UHOSTLEN];
   char userip[UHOSTLEN];
   char userip[UHOSTLEN];
   char from[NICKLEN + UHOSTLEN];   /* nick!user@host */
   char from[NICKLEN + UHOSTLEN];   /* nick!user@host */
@@ -56,6 +60,13 @@ typedef struct memstruct {
   bool is_me;
   bool is_me;
   bd::HashTable<flood_t, time_t>     *floodtime; // floodtime[FLOOD_PRIVMSG] = now;
   bd::HashTable<flood_t, time_t>     *floodtime; // floodtime[FLOOD_PRIVMSG] = now;
   bd::HashTable<flood_t, int>         *floodnum; // floodnum[FLOOD_PRIVMSG] = 1;
   bd::HashTable<flood_t, int>         *floodnum; // floodnum[FLOOD_PRIVMSG] = 1;
+
+  void* operator new (size_t size) noexcept {
+    return calloc(1, size);
+  }
+  void operator delete (void* p) noexcept {
+    free(p);
+  }
 } memberlist;
 } memberlist;
 
 
 namespace std {
 namespace std {
@@ -175,6 +186,8 @@ struct chan_t {
 
 
   // Member caching to cache cyclers
   // Member caching to cache cyclers
   bd::HashTable<bd::String, memberlist*> *cached_members;
   bd::HashTable<bd::String, memberlist*> *cached_members;
+
+  bd::HashTable<RfcString, memberlist*> *hashed_members;
 };
 };
 
 
 #define CHANINV    BIT0		/* +i					*/
 #define CHANINV    BIT0		/* +i					*/

+ 22 - 39
src/chanprog.cc

@@ -55,8 +55,11 @@
 #endif
 #endif
 #include <sys/utsname.h>
 #include <sys/utsname.h>
 #include <bdlib/src/Array.h>
 #include <bdlib/src/Array.h>
+#include <bdlib/src/HashTable.h>
 #include <bdlib/src/String.h>
 #include <bdlib/src/String.h>
 
 
+bd::HashTable<RfcString, struct chanset_t *> chanset_by_dname;
+
 char *def_chanset = "+enforcebans +dynamicbans +userbans -bitch +cycle -inactive +userexempts -dynamicexempts +userinvites -dynamicinvites -nodesynch -closed -take -voice -private -fastop ban-type 3 protect-backup 1 groups { main } revenge react";
 char *def_chanset = "+enforcebans +dynamicbans +userbans -bitch +cycle -inactive +userexempts -dynamicexempts +userinvites -dynamicinvites -nodesynch -closed -take -voice -private -fastop ban-type 3 protect-backup 1 groups { main } revenge react";
 struct chanset_t 	*chanset = NULL;	/* Channel list			*/
 struct chanset_t 	*chanset = NULL;	/* Channel list			*/
 struct chanset_t	*chanset_default = NULL;	/* Default channel list */
 struct chanset_t	*chanset_default = NULL;	/* Default channel list */
@@ -92,19 +95,6 @@ void rmspace(char *s)
     memmove(s, p, q - p + 2);
     memmove(s, p, q - p + 2);
 }
 }
 
 
-/* Returns memberfields if the nick is in the member list.
- */
-memberlist *ismember(const struct chanset_t *chan, const char *nick)
-{
-  memberlist	*x = NULL;
-
-  if (chan && nick && nick[0])
-    for (x = chan->channel.member; x && x->nick[0]; x = x->next)
-      if (!rfc_casecmp(x->nick, nick))
-        return x;
-  return NULL;
-}
-
 /* Find a chanset by channel name as the server knows it (ie !ABCDEchannel)
 /* Find a chanset by channel name as the server knows it (ie !ABCDEchannel)
  */
  */
 struct chanset_t *findchan(const char *name)
 struct chanset_t *findchan(const char *name)
@@ -117,18 +107,6 @@ struct chanset_t *findchan(const char *name)
   return NULL;
   return NULL;
 }
 }
 
 
-/* Find a chanset by display name (ie !channel)
- */
-struct chanset_t *findchan_by_dname(const char *name)
-{
-  struct chanset_t	*chan = NULL;
-
-  for (chan = chanset; chan; chan = chan->next)
-    if (!rfc_casecmp(chan->dname, name))
-      return chan;
-  return NULL;
-}
-
 /*
 /*
  *    "caching" functions
  *    "caching" functions
  */
  */
@@ -139,8 +117,8 @@ struct chanset_t *findchan_by_dname(const char *name)
 struct userrec *check_chanlist(const char *host)
 struct userrec *check_chanlist(const char *host)
 {
 {
   char				*nick = NULL, *uhost = NULL, buf[UHOSTLEN] = "";
   char				*nick = NULL, *uhost = NULL, buf[UHOSTLEN] = "";
-  memberlist		*m = NULL;
-  struct chanset_t	*chan = NULL;
+  const memberlist		*m = NULL;
+  const struct chanset_t	*chan = NULL;
 
 
   strlcpy(buf, host, sizeof buf);
   strlcpy(buf, host, sizeof buf);
   uhost = buf;
   uhost = buf;
@@ -156,8 +134,8 @@ struct userrec *check_chanlist(const char *host)
  */
  */
 struct userrec *check_chanlist_hand(const char *hand)
 struct userrec *check_chanlist_hand(const char *hand)
 {
 {
-  struct chanset_t	*chan = NULL;
-  memberlist		*m = NULL;
+  const struct chanset_t	*chan = NULL;
+  const memberlist		*m = NULL;
 
 
   for (chan = chanset; chan; chan = chan->next)
   for (chan = chanset; chan; chan = chan->next)
     for (m = chan->channel.member; m && m->nick[0]; m = m->next)
     for (m = chan->channel.member; m && m->nick[0]; m = m->next)
@@ -366,8 +344,10 @@ void reaffirm_owners()
 }
 }
 
 
 bool is_hub(const char* nick) {
 bool is_hub(const char* nick) {
+  bd::String hub(size_t(HANDLEN));
+
   for (size_t idx = 0; idx < conf.hubs.length(); ++idx) {
   for (size_t idx = 0; idx < conf.hubs.length(); ++idx) {
-    bd::String hub(conf.hubs[idx]);
+    hub = conf.hubs[idx];
     if (!strncasecmp(nick, newsplit(hub).c_str(), HANDLEN)) {
     if (!strncasecmp(nick, newsplit(hub).c_str(), HANDLEN)) {
       return true;
       return true;
     }
     }
@@ -696,14 +676,14 @@ void setup_HQ(int n) {
 
 
 /* Oddly enough, written by proton (Emech's coder)
 /* Oddly enough, written by proton (Emech's coder)
  */
  */
-int isowner(char *name)
+int isowner(const char *name)
 {
 {
   if (!owner[0])
   if (!owner[0])
     return (0);
     return (0);
   if (!name || !name[0])
   if (!name || !name[0])
     return (0);
     return (0);
 
 
-  char *pa = owner, *pb = owner;
+  const char *pa = owner, *pb = owner;
   size_t nl = strlen(name), pl;
   size_t nl = strlen(name), pl;
 
 
   while (1) {
   while (1) {
@@ -726,7 +706,8 @@ int isowner(char *name)
   }
   }
 }
 }
 
 
-bool bot_shouldjoin(struct userrec* u, struct flag_record* fr, const struct chanset_t* chan, bool ignore_inactive)
+bool bot_shouldjoin(struct userrec* u, const struct flag_record* fr,
+    const struct chanset_t* chan, bool ignore_inactive)
 {
 {
   // If restarting, keep this channel.
   // If restarting, keep this channel.
   if (restarting && (reset_chans == 2) && (channel_active(chan) || channel_pending(chan))) return 1;
   if (restarting && (reset_chans == 2) && (channel_active(chan) || channel_pending(chan))) return 1;
@@ -832,11 +813,11 @@ int do_chanset(char *result, struct chanset_t *chan, const char *options, int fl
   return ret;
   return ret;
 }
 }
 
 
-char *
+const char *
 samechans(const char *nick, const char *delim)
 samechans(const char *nick, const char *delim)
 {
 {
   static char ret[1024] = "";
   static char ret[1024] = "";
-  struct chanset_t *chan = NULL;
+  const struct chanset_t *chan = NULL;
 
 
   ret[0] = 0;		/* may be filled from last time */
   ret[0] = 0;		/* may be filled from last time */
   for (chan = chanset; chan; chan = chan->next) {
   for (chan = chanset; chan; chan = chan->next) {
@@ -849,7 +830,9 @@ samechans(const char *nick, const char *delim)
   return ret;
   return ret;
 }
 }
 
 
-static struct chanset_t* find_common_opped_chan(bd::String nick) {
+static struct chanset_t*
+__attribute__((pure))
+find_common_opped_chan(const bd::String& nick) {
   for (struct chanset_t* chan = chanset; chan; chan = chan->next) {
   for (struct chanset_t* chan = chanset; chan; chan = chan->next) {
     if (channel_active(chan) && (me_op(chan) || me_voice(chan))) {
     if (channel_active(chan) && (me_op(chan) || me_voice(chan))) {
       if (ismember(chan, nick.c_str()))
       if (ismember(chan, nick.c_str()))
@@ -859,7 +842,7 @@ static struct chanset_t* find_common_opped_chan(bd::String nick) {
   return NULL;
   return NULL;
 }
 }
 
 
-void privmsg(bd::String target, bd::String msg, int idx) {
+void privmsg(const bd::String& target, bd::String msg, int idx) {
   struct chanset_t* chan = NULL;
   struct chanset_t* chan = NULL;
   bool talking_to_chan = strchr(CHANMETA, target[0]);
   bool talking_to_chan = strchr(CHANMETA, target[0]);
   if (have_cprivmsg && !talking_to_chan)
   if (have_cprivmsg && !talking_to_chan)
@@ -881,7 +864,7 @@ void privmsg(bd::String target, bd::String msg, int idx) {
     dprintf(idx, "PRIVMSG %s :%s\n", target.c_str(), msg.c_str());
     dprintf(idx, "PRIVMSG %s :%s\n", target.c_str(), msg.c_str());
 }
 }
 
 
-void notice(bd::String target, bd::String msg, int idx) {
+void notice(const bd::String& target, bd::String msg, int idx) {
   struct chanset_t* chan = NULL;
   struct chanset_t* chan = NULL;
   bool talking_to_chan = strchr(CHANMETA, target[0]);
   bool talking_to_chan = strchr(CHANMETA, target[0]);
   if (have_cnotice && !talking_to_chan)
   if (have_cnotice && !talking_to_chan)
@@ -919,7 +902,7 @@ void keyx(const bd::String &target, const char *reason) {
   FishKeys[target] = fishData;
   FishKeys[target] = fishData;
 }
 }
 
 
-void set_fish_key(char *target, bd::String key)
+void set_fish_key(const char *target, const bd::String key)
 {
 {
   fish_data_t* fishData = FishKeys.contains(target) ? FishKeys[target] : NULL;
   fish_data_t* fishData = FishKeys.contains(target) ? FishKeys[target] : NULL;
 
 

+ 37 - 12
src/chanprog.h

@@ -2,17 +2,20 @@
 #define _CHANPROG_H
 #define _CHANPROG_H
 
 
 #include "src/chan.h"
 #include "src/chan.h"
+#include "RfcString.h"
 
 
 #define DO_LOCAL	1
 #define DO_LOCAL	1
 #define DO_NET		2
 #define DO_NET		2
 #define CMD		4
 #define CMD		4
 
 
+extern bd::HashTable<RfcString, struct chanset_t *> chanset_by_dname;
+
 int do_chanset(char *, struct chanset_t *, const char *, int);
 int do_chanset(char *, struct chanset_t *, const char *, int);
 void checkchans(int);
 void checkchans(int);
 void tell_verbose_uptime(int);
 void tell_verbose_uptime(int);
 void tell_verbose_status(int);
 void tell_verbose_status(int);
 void tell_settings(int);
 void tell_settings(int);
-int isowner(char *);
+int isowner(const char *) __attribute__((pure));
 void reaffirm_owners();
 void reaffirm_owners();
 void reload();
 void reload();
 void chanprog();
 void chanprog();
@@ -23,23 +26,45 @@ void rmspace(char *s);
 void set_chanlist(const char *host, struct userrec *rec);
 void set_chanlist(const char *host, struct userrec *rec);
 void clear_chanlist_member(const char *nick);
 void clear_chanlist_member(const char *nick);
 #define clear_chanlist() clear_chanlist_member(NULL)
 #define clear_chanlist() clear_chanlist_member(NULL)
-bool bot_shouldjoin(struct userrec* , struct flag_record *, const struct chanset_t *, bool = 0);
+bool bot_shouldjoin(struct userrec*, const struct flag_record *, const struct chanset_t *, bool = 0);
 bool shouldjoin(const struct chanset_t *);
 bool shouldjoin(const struct chanset_t *);
-char *samechans(const char *, const char *);
+const char *samechans(const char *, const char *);
 void add_myself_to_userlist();
 void add_myself_to_userlist();
 void add_child_bots();
 void add_child_bots();
-bool is_hub(const char*);
+bool is_hub(const char*) __attribute__((pure));
 void load_internal_users();
 void load_internal_users();
 void setup_HQ(int);
 void setup_HQ(int);
-void privmsg(bd::String target, bd::String msg, int idx);
-void notice(bd::String target, bd::String msg, int idx);
+void privmsg(const bd::String& target, bd::String msg, int idx);
+void notice(const bd::String& target, bd::String msg, int idx);
 void keyx(const bd::String& target, const char *);
 void keyx(const bd::String& target, const char *);
-void set_fish_key(char *, bd::String);
-struct userrec *check_chanlist(const char *);
-struct userrec *check_chanlist_hand(const char *);
-memberlist *ismember(const struct chanset_t *, const char *);
-struct chanset_t *findchan(const char *name);
-struct chanset_t *findchan_by_dname(const char *name);
+void set_fish_key(const char *, const bd::String);
+struct userrec *check_chanlist(const char *) __attribute__((pure));
+struct userrec *check_chanlist_hand(const char *) __attribute__((pure));
+/*
+ * Returns memberfields if the nick is in the member list.
+ */
+static inline memberlist *
+__attribute__((pure))
+ismember(const struct chanset_t *chan, const RfcString& nick) {
+  if (!chan || !nick)
+    return NULL;
+  auto kv = chan->channel.hashed_members->find(nick);
+  if (kv == chan->channel.hashed_members->end())
+    return NULL;
+  return kv->second;
+}
+struct chanset_t *findchan(const char *name) __attribute__((pure));
+/*
+ * Find a chanset by display name (ie !channel)
+ */
+static inline struct chanset_t *
+__attribute__((pure))
+findchan_by_dname(const RfcString& name) {
+  auto kv = chanset_by_dname.find(name);
+  if (kv == chanset_by_dname.end())
+    return NULL;
+  return kv->second;
+}
 
 
 extern struct chanset_t		*chanset, *chanset_default;
 extern struct chanset_t		*chanset, *chanset_default;
 extern char			admin[], origbotnick[HANDLEN + 1], origbotname[NICKLEN], jupenick[NICKLEN], botname[NICKLEN], *def_chanset;
 extern char			admin[], origbotnick[HANDLEN + 1], origbotname[NICKLEN], jupenick[NICKLEN], botname[NICKLEN], *def_chanset;

+ 7 - 17
src/cmds.cc

@@ -608,21 +608,13 @@ static void cmd_nohelp(int idx, char *par)
   dumplots(idx, "", buf);
   dumplots(idx, "", buf);
 }
 }
 
 
-bool is_restricted_cmd(const char* name) {
-  if (name) {
-    if (!HAVE_MDOP && !strcasecmp(name, "mmode"))
-      return 1;
-  }
-  return 0;
-}
-
 static int comp_help_t(const void *m1, const void *m2) {
 static int comp_help_t(const void *m1, const void *m2) {
   const help_t *mi1 = (const help_t *) m1;
   const help_t *mi1 = (const help_t *) m1;
   const help_t *mi2 = (const help_t *) m2;
   const help_t *mi2 = (const help_t *) m2;
   return strcasecmp(mi1->cmd, mi2->cmd);
   return strcasecmp(mi1->cmd, mi2->cmd);
 }
 }
 
 
-help_t *
+const help_t *
 findcmd(const char *lookup, bool care_about_type)
 findcmd(const char *lookup, bool care_about_type)
 {
 {
   help_t key;
   help_t key;
@@ -679,7 +671,7 @@ static void cmd_help(int idx, char *par)
         flg[0] = 0;
         flg[0] = 0;
         build_flags(flg, &(cmdlist[n].flags), NULL);
         build_flags(flg, &(cmdlist[n].flags), NULL);
         dprintf(idx, "Showing you help for '%s' (%s):\n", match, flg);
         dprintf(idx, "Showing you help for '%s' (%s):\n", match, flg);
-        help_t *h_entry = NULL;
+        const help_t *h_entry = NULL;
         if ((h_entry = findhelp(match)) != NULL) {
         if ((h_entry = findhelp(match)) != NULL) {
           if (h_entry->garble_len)
           if (h_entry->garble_len)
             showhelp(idx, &fr, degarble(h_entry->garble_len, h_entry->desc));
             showhelp(idx, &fr, degarble(h_entry->garble_len, h_entry->desc));
@@ -930,8 +922,7 @@ static void cmd_groups(int idx, char *par)
     if (u->bot && bot_hublevel(u) == 999) {
     if (u->bot && bot_hublevel(u) == 999) {
       // Gather all the groups for this bot
       // Gather all the groups for this bot
       botGroups[u->handle] = bd::String(var_get_bot_data(u, "groups", true)).split(",");
       botGroups[u->handle] = bd::String(var_get_bot_data(u, "groups", true)).split(",");
-      for (size_t i = 0; i < botGroups[u->handle].length(); ++i) {
-        const bd::String group(botGroups[u->handle][i]);
+      for (const auto& group : botGroups[u->handle]) {
         if (group.length() > maxGroupLen) {
         if (group.length() > maxGroupLen) {
           maxGroupLen = group.length();
           maxGroupLen = group.length();
         }
         }
@@ -951,8 +942,7 @@ static void cmd_groups(int idx, char *par)
     dprintf(idx, "Total groups: %zu/%zu\n", botGroups[botnick].length(), allgroups.length());
     dprintf(idx, "Total groups: %zu/%zu\n", botGroups[botnick].length(), allgroups.length());
   } else {
   } else {
     // Display all groups and which bots are in them
     // Display all groups and which bots are in them
-    for (size_t i = 0; i < allgroups.length(); ++i) {
-      const bd::String group(allgroups[i]);
+    for (const auto& group : allgroups) {
       const bd::Array<bd::String> bots(groupBots[group]);
       const bd::Array<bd::String> bots(groupBots[group]);
       dumplots(idx, bd::String::printf("%-*s: ", int(maxGroupLen), group.c_str()).c_str(), static_cast<bd::String>(bots.join(" ")).c_str());
       dumplots(idx, bd::String::printf("%-*s: ", int(maxGroupLen), group.c_str()).c_str(), static_cast<bd::String>(bots.join(" ")).c_str());
     }
     }
@@ -3033,7 +3023,7 @@ static void cmd_color(int idx, char *par)
   console_dostore(idx);
   console_dostore(idx);
 }
 }
 
 
-int stripmodes(char *s)
+int stripmodes(const char *s)
 {
 {
   int res = 0;
   int res = 0;
 
 
@@ -3064,7 +3054,7 @@ int stripmodes(char *s)
   return res;
   return res;
 }
 }
 
 
-char *stripmasktype(int x)
+const char *stripmasktype(int x)
 {
 {
   static char s[20] = "";
   static char s[20] = "";
   char *p = s;
   char *p = s;
@@ -3087,7 +3077,7 @@ char *stripmasktype(int x)
   return s;
   return s;
 }
 }
 
 
-static char *stripmaskname(int x)
+static const char *stripmaskname(int x)
 {
 {
   static char s[161] = "";
   static char s[161] = "";
   size_t i = 0;
   size_t i = 0;

+ 14 - 5
src/cmds.h

@@ -3,8 +3,6 @@
 
 
 #include "types.h"
 #include "types.h"
 
 
-bool is_restricted_cmd(const char*);
-
 typedef struct {
 typedef struct {
   const char          *name;
   const char          *name;
   const char          *flags;
   const char          *flags;
@@ -44,12 +42,23 @@ typedef struct cmd_pass {
 extern mycmds 		cmdlist[]; 
 extern mycmds 		cmdlist[]; 
 extern int		cmdi;
 extern int		cmdi;
 
 
+static inline bool
+__attribute__((pure))
+is_restricted_cmd(const char* name)
+{
+  if (name) {
+    if (!HAVE_MDOP && !strcasecmp(name, "mmode"))
+      return 1;
+  }
+  return 0;
+}
+
 #define findhelp(x) findcmd(x, 1)
 #define findhelp(x) findcmd(x, 1)
-help_t *findcmd(const char *lookup, bool care_about_type);
+const help_t *findcmd(const char *lookup, bool care_about_type) __attribute__((pure));
 int check_dcc_attrs(struct userrec *, flag_t);
 int check_dcc_attrs(struct userrec *, flag_t);
 int check_dcc_chanattrs(struct userrec *, char *, flag_t, flag_t);
 int check_dcc_chanattrs(struct userrec *, char *, flag_t, flag_t);
-int stripmodes(char *);
-char *stripmasktype(int);
+int stripmodes(const char *) __attribute__((pure));
+const char *stripmasktype(int);
 void gotremotecmd(char * forbot, char * frombot, char * fromhand, char * fromidx, char * cmd);
 void gotremotecmd(char * forbot, char * frombot, char * fromhand, char * fromidx, char * cmd);
 void gotremotereply(char * frombot, char * tohand, char * toidx, char * ln);
 void gotremotereply(char * frombot, char * tohand, char * toidx, char * ln);
 
 

+ 0 - 14
src/conf.cc

@@ -1137,20 +1137,6 @@ void conf_add_userlist_bots()
 
 
 }
 }
 
 
-conf_bot *conf_getlocalhub(conf_bot *bots) {
-  if (!bots)
-    return NULL;
-
-  conf_bot *localhub = bots;
-  if (localhub->disabled)
-    while (localhub && localhub->disabled)
-      localhub = localhub->next;
-
-  if (!localhub) return NULL;
-  return !localhub->disabled ? localhub : NULL;
-}
-
-
 void conf_setmypid(pid_t pid) {
 void conf_setmypid(pid_t pid) {
   conf.bot->pid = pid;
   conf.bot->pid = pid;
   conf_bot *bot = conf.bots;
   conf_bot *bot = conf.bots;

+ 0 - 1
src/conf.h

@@ -72,7 +72,6 @@ void conf_checkpids(conf_bot *bots, bool all = 1);
 void conf_add_userlist_bots();
 void conf_add_userlist_bots();
 conf_bot *conf_bots_dup(conf_bot *);
 conf_bot *conf_bots_dup(conf_bot *);
 void deluser_removed_bots(conf_bot *, conf_bot *);
 void deluser_removed_bots(conf_bot *, conf_bot *);
-conf_bot *conf_getlocalhub(conf_bot *);
 void conf_setmypid(pid_t);
 void conf_setmypid(pid_t);
 void conf_bot_dup(conf_bot *dest, conf_bot *src);
 void conf_bot_dup(conf_bot *dest, conf_bot *src);
 void conf_update_hubs(struct userrec* list);
 void conf_update_hubs(struct userrec* list);

+ 0 - 2
src/crypt.h

@@ -29,8 +29,6 @@ char *encrypt_string(const char *, char *);
 char *decrypt_string(const char *, char *);
 char *decrypt_string(const char *, char *);
 char *salted_sha1(const char *, const char* = NULL);
 char *salted_sha1(const char *, const char* = NULL);
 int salted_sha1cmp(const char *, const char*);
 int salted_sha1cmp(const char *, const char*);
-char *cryptit (char *);
-char *decryptit (char *);
 void Encrypt_File(char *, char *);
 void Encrypt_File(char *, char *);
 void Decrypt_File(char *, char *);
 void Decrypt_File(char *, char *);
 void btoh(const unsigned char *md, size_t md_len, char *buf, const size_t buf_len);
 void btoh(const unsigned char *md, size_t md_len, char *buf, const size_t buf_len);

+ 4 - 3
src/dcc.cc

@@ -1145,7 +1145,8 @@ struct dcc_table DCC_CHAT_PASS = {
 /* Make sure ansi code is just for color-changing
 /* Make sure ansi code is just for color-changing
  */
  */
 static int
 static int
-check_ansi(char *v)
+__attribute__((pure))
+check_ansi(const char *v)
 {
 {
   int count = 2;
   int count = 2;
 
 
@@ -1164,9 +1165,9 @@ check_ansi(char *v)
   return count;
   return count;
 }
 }
 
 
-int ansi_len(char *s)
+int ansi_len(const char *s)
 {
 {
-  char *c = s;
+  const char *c = s;
   int count = 0;
   int count = 0;
 
 
   while (*c) {
   while (*c) {

+ 1 - 1
src/dcc.h

@@ -241,6 +241,6 @@ void send_timesync(int);
 void failed_link(int);
 void failed_link(int);
 void dupwait_notify(const char *);
 void dupwait_notify(const char *);
 void send_sysinfo();
 void send_sysinfo();
-int ansi_len(char *);
+int ansi_len(const char *) __attribute__((pure));
 
 
 #endif /* !_DCC_H */
 #endif /* !_DCC_H */

+ 2 - 10
src/dccutil.cc

@@ -1119,17 +1119,9 @@ identd_close()
   }
   }
 }
 }
 
 
-bool
-valid_idx(int idx)
-{
-  if ((idx == -1) || (idx >= dcc_total) || (!dcc[idx].type))
-    return 0;
-  return 1;
-}
-
 int check_cmd_pass(const char *cmd, char *pass)
 int check_cmd_pass(const char *cmd, char *pass)
 {
 {
-  struct cmd_pass *cp = NULL;
+  const struct cmd_pass *cp = NULL;
 
 
   for (cp = cmdpass; cp; cp = cp->next)
   for (cp = cmdpass; cp; cp = cp->next)
     if (!strcasecmp(cmd, cp->name)) {
     if (!strcasecmp(cmd, cp->name)) {
@@ -1166,7 +1158,7 @@ int check_cmd_pass(const char *cmd, char *pass)
 
 
 int has_cmd_pass(const char *cmd)
 int has_cmd_pass(const char *cmd)
 {
 {
-  struct cmd_pass *cp = NULL;
+  const struct cmd_pass *cp = NULL;
 
 
   for (cp = cmdpass; cp; cp = cp->next)
   for (cp = cmdpass; cp; cp = cp->next)
     if (!strcasecmp(cmd, cp->name))
     if (!strcasecmp(cmd, cp->name))

+ 9 - 3
src/dccutil.h

@@ -52,7 +52,6 @@ void not_away(int);
 void set_away(int, char *);
 void set_away(int, char *);
 void dcc_remove_lost(void);
 void dcc_remove_lost(void);
 void flush_lines(int, struct chat_info *);
 void flush_lines(int, struct chat_info *);
-struct dcc_t *find_idx(int);
 int new_dcc(struct dcc_table *, int);
 int new_dcc(struct dcc_table *, int);
 void del_dcc(int);
 void del_dcc(int);
 char *add_cr(char *);
 char *add_cr(char *);
@@ -62,11 +61,18 @@ int detect_dcc_flood(time_t *, struct chat_info *, int);
 void identd_open(const char * = NULL, const char * = NULL, int identd = 1);
 void identd_open(const char * = NULL, const char * = NULL, int identd = 1);
 void identd_close();
 void identd_close();
 int listen_all(in_port_t, bool, bool);
 int listen_all(in_port_t, bool, bool);
-bool valid_idx(int);
+static inline bool __attribute__((pure))
+valid_idx(int idx)
+{
+  if ((idx == -1) || (idx >= dcc_total) || (!dcc[idx].type))
+    return false;
+  return true;
+}
+
 int dcc_read(bd::Stream&);
 int dcc_read(bd::Stream&);
 void dcc_write(bd::Stream&, int);
 void dcc_write(bd::Stream&, int);
 int check_cmd_pass(const char *, char *);
 int check_cmd_pass(const char *, char *);
-int has_cmd_pass(const char *);
+int has_cmd_pass(const char *) __attribute__((pure));
 void set_cmd_pass(char *, int);
 void set_cmd_pass(char *, int);
 void cmdpass_free(struct cmd_pass *);
 void cmdpass_free(struct cmd_pass *);
 
 

+ 2 - 1
src/egg_timer.h

@@ -20,7 +20,8 @@ void timer_get_now(egg_timeval_t *_now);
 int timer_get_now_sec(int *sec);
 int timer_get_now_sec(int *sec);
 void timer_update_now(egg_timeval_t *_now);
 void timer_update_now(egg_timeval_t *_now);
 int timer_diff(egg_timeval_t *from_time, egg_timeval_t *to_time, egg_timeval_t *diff);
 int timer_diff(egg_timeval_t *from_time, egg_timeval_t *to_time, egg_timeval_t *diff);
-long timeval_diff(const egg_timeval_t *tv1, const egg_timeval_t *tv2);
+long timeval_diff(const egg_timeval_t *tv1, const egg_timeval_t *tv2)
+  __attribute__((pure));
 int timer_create_secs(int, const char *, Function);
 int timer_create_secs(int, const char *, Function);
 int timer_create_complex(egg_timeval_t *howlong, const char *name, Function callback, void *client_data, int flags);
 int timer_create_complex(egg_timeval_t *howlong, const char *name, Function callback, void *client_data, int flags);
 int timer_destroy(int timer_id);
 int timer_destroy(int timer_id);

+ 2 - 2
src/flags.cc

@@ -299,7 +299,7 @@ build_flags(char *string, struct flag_record *plus, struct flag_record *minus)
 
 
 /* Returns 1 if flags match, 0 if they don't. */
 /* Returns 1 if flags match, 0 if they don't. */
 int
 int
-flagrec_ok(struct flag_record *req, struct flag_record *have)
+flagrec_ok(const struct flag_record *req, const struct flag_record *have)
 {
 {
   if (req->match & FR_AND) {
   if (req->match & FR_AND) {
     return flagrec_eq(req, have);
     return flagrec_eq(req, have);
@@ -320,7 +320,7 @@ flagrec_ok(struct flag_record *req, struct flag_record *have)
 
 
 /* Returns 1 if flags match, 0 if they don't. */
 /* Returns 1 if flags match, 0 if they don't. */
 int
 int
-flagrec_eq(struct flag_record *req, struct flag_record *have)
+flagrec_eq(const struct flag_record *req, const struct flag_record *have)
 {
 {
   if (req->match & FR_AND) {
   if (req->match & FR_AND) {
     if (req->match & FR_GLOBAL) {
     if (req->match & FR_GLOBAL) {

+ 13 - 11
src/flags.h

@@ -167,18 +167,20 @@ void get_user_flagrec(const struct userrec *, struct flag_record *, const char *
 void set_user_flagrec(struct userrec *, struct flag_record *, const char *);
 void set_user_flagrec(struct userrec *, struct flag_record *, const char *);
 void break_down_flags(const char *, struct flag_record *, struct flag_record *);
 void break_down_flags(const char *, struct flag_record *, struct flag_record *);
 int build_flags(char *, struct flag_record *, struct flag_record *);
 int build_flags(char *, struct flag_record *, struct flag_record *);
-int flagrec_eq(struct flag_record *, struct flag_record *);
-int flagrec_ok(struct flag_record *, struct flag_record *);
-flag_t sanity_check(flag_t, int);
-flag_t chan_sanity_check(flag_t, int);
+int flagrec_eq(const struct flag_record *, const struct flag_record *)
+  __attribute__((pure));
+int flagrec_ok(const struct flag_record *, const struct flag_record *)
+  __attribute__((pure));
+flag_t sanity_check(flag_t, int) __attribute__((const));
+flag_t chan_sanity_check(flag_t, int) __attribute__((const));
 char geticon(int);
 char geticon(int);
-int privchan(const struct flag_record, const struct chanset_t *, int);
+int privchan(const struct flag_record, const struct chanset_t *, int) __attribute__((pure));
 #define chk_op(fr, chan) real_chk_op(fr, chan, 1)
 #define chk_op(fr, chan) real_chk_op(fr, chan, 1)
-int real_chk_op(const struct flag_record, const struct chanset_t *, bool);
-int chk_autoop(const memberlist *, const struct flag_record, const struct chanset_t *);
+int real_chk_op(const struct flag_record, const struct chanset_t *, bool) __attribute__((pure));
+int chk_autoop(const memberlist *, const struct flag_record, const struct chanset_t *) __attribute__((pure));
 #define chk_deop(fr, chan) real_chk_deop(fr, chan, 1)
 #define chk_deop(fr, chan) real_chk_deop(fr, chan, 1)
-int real_chk_deop(const struct flag_record, const struct chanset_t *, bool);
-int chk_voice(const memberlist *, const struct flag_record, const struct chanset_t *);
+int real_chk_deop(const struct flag_record, const struct chanset_t *, bool) __attribute__((pure));
+int chk_voice(const memberlist *, const struct flag_record, const struct chanset_t *) __attribute__((pure));
 #define chk_noflood(fr) (chan_noflood(fr) || glob_noflood(fr))
 #define chk_noflood(fr) (chan_noflood(fr) || glob_noflood(fr))
 #define chk_devoice(fr) ((chan_quiet(fr) || (glob_quiet(fr) && !chan_voice(fr))) ? 1 : 0)
 #define chk_devoice(fr) ((chan_quiet(fr) || (glob_quiet(fr) && !chan_voice(fr))) ? 1 : 0)
 #define isupdatehub() ((conf.bot->hub && conf.bot->u && (conf.bot->u->flags & BOT_UPDATEHUB)) ? 1 : 0)
 #define isupdatehub() ((conf.bot->hub && conf.bot->u && (conf.bot->u->flags & BOT_UPDATEHUB)) ? 1 : 0)
@@ -188,9 +190,9 @@ int dovoice(const struct chanset_t *);
 int doflood(const struct chanset_t *);
 int doflood(const struct chanset_t *);
 int dolimit(const struct chanset_t *);
 int dolimit(const struct chanset_t *);
 int whois_access(struct userrec *, struct userrec *);
 int whois_access(struct userrec *, struct userrec *);
-homechan_user_t homechan_user_translate(const char *);
+homechan_user_t homechan_user_translate(const char *) __attribute__((pure));
 void deflag_user(struct userrec *, deflag_event_t, const char *, const struct chanset_t *);
 void deflag_user(struct userrec *, deflag_event_t, const char *, const struct chanset_t *);
-deflag_t deflag_translate(const char *);
+deflag_t deflag_translate(const char *) __attribute__((pure));
 
 
 
 
 #endif				/* _EGG_FLAGS_H */
 #endif				/* _EGG_FLAGS_H */

+ 1 - 1
src/garble.cc

@@ -10,7 +10,7 @@
 #include "main.h"
 #include "main.h"
 
 
 #define GARBLE_BUFFERS 40
 #define GARBLE_BUFFERS 40
-unsigned char *garble_buffer[GARBLE_BUFFERS] = {
+static unsigned char *garble_buffer[GARBLE_BUFFERS] = {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 };

+ 2 - 2
src/log.cc

@@ -85,7 +85,7 @@ static logmode_mapping_t logmode_mappings[] = {
 
 
 int logmodes(const char *s)
 int logmodes(const char *s)
 {
 {
-	logmode_mapping_t *mapping = NULL;
+	const logmode_mapping_t *mapping = NULL;
 	int modes = 0;
 	int modes = 0;
 
 
 	while (*s) {
 	while (*s) {
@@ -119,7 +119,7 @@ char *masktype(int x)
 char *maskname(int x)
 char *maskname(int x)
 {
 {
 	static char s[1024] = "";
 	static char s[1024] = "";
-	logmode_mapping_t *mapping = NULL;
+	const logmode_mapping_t *mapping = NULL;
 	int len;
 	int len;
 
 
 	*s = 0;
 	*s = 0;

+ 1 - 1
src/log.h

@@ -30,7 +30,7 @@
 
 
 void logidx(int, const char *, ...) __attribute__((format(printf, 2, 3)));
 void logidx(int, const char *, ...) __attribute__((format(printf, 2, 3)));
 void putlog (int, const char *, const char *, ...) __attribute__((format(printf, 3, 4)));
 void putlog (int, const char *, const char *, ...) __attribute__((format(printf, 3, 4)));
-int logmodes(const char *);
+int logmodes(const char *) __attribute__((pure));
 char *masktype(int);
 char *masktype(int);
 char *maskname(int);
 char *maskname(int);
 #if 0
 #if 0

+ 7 - 7
src/match.cc

@@ -64,13 +64,13 @@
 #define PERMATCH (match+saved+sofar)
 #define PERMATCH (match+saved+sofar)
 
 
 /* binds matching */
 /* binds matching */
-int _wild_match_per(unsigned char *m, unsigned char *n)
+int _wild_match_per(const unsigned char *m, const unsigned char *n)
 {
 {
   /* null strings should never match */
   /* null strings should never match */
   if ((m == 0) || (n == 0) || (!*n))
   if ((m == 0) || (n == 0) || (!*n))
     return NOMATCH;
     return NOMATCH;
 
 
-  unsigned char *ma = m, *lsm = NULL, *lsn = NULL, *lpm = NULL, *lpn = NULL;
+  const unsigned char *ma = m, *lsm = NULL, *lsn = NULL, *lpm = NULL, *lpn = NULL;
   int match = 1, saved = 0, space;
   int match = 1, saved = 0, space;
   int sofar = 0;
   int sofar = 0;
 
 
@@ -130,7 +130,7 @@ int _wild_match_per(unsigned char *m, unsigned char *n)
       case QUOTE:
       case QUOTE:
         m++;                    /* Handle quoting */
         m++;                    /* Handle quoting */
       }
       }
-      if (rfc_toupper(*m) == rfc_toupper(*n)) { /* If matching */
+      if (rfc_char_equal(*m, *n)) { /* If matching */
         m++;
         m++;
         n++;
         n++;
         sofar++;
         sofar++;
@@ -162,15 +162,15 @@ int _wild_match_per(unsigned char *m, unsigned char *n)
 
 
 
 
 /* general/host matching */
 /* general/host matching */
-int _wild_match(unsigned char *m, unsigned char *n)
+int _wild_match(const unsigned char *m, const unsigned char *n)
 {
 {
-  unsigned char *ma = m, *na = n;
+  const unsigned char *ma = m, *na = n;
 
 
   /* null strings should never match */
   /* null strings should never match */
   if ((ma == 0) || (na == 0) || (!*ma) || (!*na))
   if ((ma == 0) || (na == 0) || (!*ma) || (!*na))
     return NOMATCH;
     return NOMATCH;
 
 
-  unsigned char *lsm = NULL, *lsn = NULL;
+  const unsigned char *lsm = NULL, *lsn = NULL;
   int match = 1;
   int match = 1;
   int sofar = 0;
   int sofar = 0;
 
 
@@ -210,7 +210,7 @@ int _wild_match(unsigned char *m, unsigned char *n)
       n--;
       n--;
       continue;                 /* '?' always matches */
       continue;                 /* '?' always matches */
     }
     }
-    if (rfc_toupper(*m) == rfc_toupper(*n)) {   /* If matching char */
+    if (rfc_char_equal(*m, *n)) {   /* If matching char */
       m--;
       m--;
       n--;
       n--;
       sofar++;                  /* Tally the match */
       sofar++;                  /* Tally the match */

+ 3 - 3
src/match.h

@@ -8,12 +8,12 @@ int wild_match_per(unsigned char *, unsigned char *);
 #define wild_match(a,b) _wild_match((unsigned char *)(a),(unsigned char *)(b))
 #define wild_match(a,b) _wild_match((unsigned char *)(a),(unsigned char *)(b))
 #define wild_match_per(a,b) _wild_match_per((unsigned char *)(a),(unsigned char *)(b))
 #define wild_match_per(a,b) _wild_match_per((unsigned char *)(a),(unsigned char *)(b))
 
 
-int _wild_match(unsigned char *, unsigned char *);
-int _wild_match_per(unsigned char *, unsigned char *);
+int _wild_match(const unsigned char *, const unsigned char *) __attribute__((pure));
+int _wild_match_per(const unsigned char *, const unsigned char *) __attribute__((pure));
 
 
 //int wild_match(char *, char *);
 //int wild_match(char *, char *);
 //int wild_match_per(char *, char *);
 //int wild_match_per(char *, char *);
 
 
-int match_cidr(const char *, const char *);
+int match_cidr(const char *, const char *) __attribute__((pure));
 
 
 #endif /* !_MATCH_H */
 #endif /* !_MATCH_H */

+ 2 - 5
src/misc.cc

@@ -445,7 +445,6 @@ void show_channels(int idx, char *handle)
   struct userrec *u = NULL;
   struct userrec *u = NULL;
   size_t maxChannelLength = 0;
   size_t maxChannelLength = 0;
   bd::Array<bd::String> channelNames;
   bd::Array<bd::String> channelNames;
-  bd::HashTable<bd::String, struct chanset_t*> channels;
   bd::String group;
   bd::String group;
 
 
   if (handle && handle[0] != '%') {
   if (handle && handle[0] != '%') {
@@ -470,7 +469,6 @@ void show_channels(int idx, char *handle)
         maxChannelLength = chname.length();
         maxChannelLength = chname.length();
       }
       }
       channelNames << chname;
       channelNames << chname;
-      channels[chname] = chan;
     }
     }
   }
   }
 
 
@@ -483,9 +481,8 @@ void show_channels(int idx, char *handle)
       dprintf(idx, "%s %s access to %zu channel%s:\n", handle ? u->handle : "You", handle ? "has" : "have", channelNames.length(), (channelNames.length() > 1) ? "s" : "");
       dprintf(idx, "%s %s access to %zu channel%s:\n", handle ? u->handle : "You", handle ? "has" : "have", channelNames.length(), (channelNames.length() > 1) ? "s" : "");
     }
     }
 
 
-    for (size_t i = 0; i < channelNames.length(); ++i) {
-      const bd::String chname(channelNames[i]);
-      const struct chanset_t* chan = channels[chname];
+    for (const auto& chname : channelNames) {
+      const struct chanset_t* chan = findchan_by_dname(chname);
       dprintf(idx, format, !conf.bot->hub && me_op(chan) ? '@' : ' ', chan->dname, ((conf.bot->hub && channel_inactive(chan)) || (!conf.bot->hub && !shouldjoin(chan))) ? "(inactive) " : "",
       dprintf(idx, format, !conf.bot->hub && me_op(chan) ? '@' : ' ', chan->dname, ((conf.bot->hub && channel_inactive(chan)) || (!conf.bot->hub && !shouldjoin(chan))) ? "(inactive) " : "",
           channel_privchan(chan) ? "(private)  " : "", chan->manop ? "(no manop) " : "", 
           channel_privchan(chan) ? "(private)  " : "", chan->manop ? "(no manop) " : "", 
           channel_bitch(chan) && !channel_botbitch(chan) ? "(bitch)    " : channel_botbitch(chan) ? "(botbitch) " : "",
           channel_bitch(chan) && !channel_botbitch(chan) ? "(bitch)    " : channel_botbitch(chan) ? "(botbitch) " : "",

+ 3 - 4
src/misc.h

@@ -16,8 +16,8 @@
 
 
 
 
 void restart(int);
 void restart(int);
-int coloridx(int);
-const char *color(int, int, int);
+int coloridx(int) __attribute__((pure));
+const char *color(int, int, int) __attribute__((pure));
 void shuffle(char *, char *, size_t);
 void shuffle(char *, char *, size_t);
 void shuffleArray(char **, size_t);
 void shuffleArray(char **, size_t);
 void showhelp(int, struct flag_record *, const char *);
 void showhelp(int, struct flag_record *, const char *);
@@ -31,7 +31,6 @@ size_t my_strcpy(char *, const char *);
 void maskaddr(const char *, char *, int);
 void maskaddr(const char *, char *, int);
 #define maskhost(a,b) maskaddr((a),(b),3)
 #define maskhost(a,b) maskaddr((a),(b),3)
 #define maskban(a,b)  maskaddr((a),(b),3)
 #define maskban(a,b)  maskaddr((a),(b),3)
-char *stristr(char *, char *);
 void splitc(char *, char *, char);
 void splitc(char *, char *, char);
 void splitcn(char *, char *, char, size_t);
 void splitcn(char *, char *, char, size_t);
 int remove_crlf(char *);
 int remove_crlf(char *);
@@ -49,7 +48,7 @@ void make_rand_str(char *, size_t, bool = 1);
 char *str_escape(const char *, const char, const char);
 char *str_escape(const char *, const char, const char);
 char *strchr_unescape(char *, const char, const char);
 char *strchr_unescape(char *, const char, const char);
 void str_unescape(char *, const char);
 void str_unescape(char *, const char);
-int str_isdigit(const char *);
+int str_isdigit(const char *) __attribute__((pure));
 void kill_bot(char *, char *);
 void kill_bot(char *, char *);
 char *strtolower(char *);
 char *strtolower(char *);
 char *strtoupper(char *);
 char *strtoupper(char *);

+ 2 - 2
src/misc_file.cc

@@ -197,7 +197,7 @@ void Tempfile::AllocTempfile()
   MakeTemp();
   MakeTemp();
 }
 }
 
 
-void Tempfile::MakeTemp()
+void Tempfile::MakeTemp() noexcept
 {
 {
   if ((fd = mkstemp(file)) < 0) {
   if ((fd = mkstemp(file)) < 0) {
     f = NULL;
     f = NULL;
@@ -284,7 +284,7 @@ static bool check_tempdir(bool do_mod)
   return 1;
   return 1;
 }
 }
 
 
-bool Tempfile::FindDir()
+bool Tempfile::FindDir() noexcept
 {
 {
   /* this is temporary until we make tmpdir customizable */
   /* this is temporary until we make tmpdir customizable */
 
 

+ 7 - 7
src/misc_file.h

@@ -13,11 +13,11 @@
 
 
 int copyfile(const char *, const char *);
 int copyfile(const char *, const char *);
 int movefile(const char *, const char *);
 int movefile(const char *, const char *);
-int is_file(const char *);
-int can_stat(const char *);
-int can_lstat(const char *);
-int is_symlink(const char *);
-int is_dir(const char *);
+int is_file(const char *) __attribute__((pure));
+int can_stat(const char *) __attribute__((pure));
+int can_lstat(const char *) __attribute__((pure));
+int is_symlink(const char *) __attribute__((pure));
+int is_dir(const char *) __attribute__((pure));
 int fixmod(const char *);
 int fixmod(const char *);
 
 
 class Tempfile 
 class Tempfile 
@@ -29,7 +29,7 @@ class Tempfile
     void AllocTempfile();			//constructor with file prefix
     void AllocTempfile();			//constructor with file prefix
     void my_close();
     void my_close();
     ~Tempfile();				//destructor
     ~Tempfile();				//destructor
-    static bool FindDir();
+    static bool FindDir() noexcept;
 
 
     bool error;					//exceptions are lame.
     bool error;					//exceptions are lame.
     FILE *f;
     FILE *f;
@@ -40,7 +40,7 @@ class Tempfile
   private:
   private:
     char *prefix;
     char *prefix;
     int plen;
     int plen;
-    void MakeTemp();				//Used for mktemp() and checking
+    void MakeTemp() noexcept;			//Used for mktemp() and checking
     bool useFopen;
     bool useFopen;
 };
 };
 
 

+ 6 - 8
src/mod/channels.mod/chanmisc.cc

@@ -978,13 +978,14 @@ static void init_channel(struct chanset_t *chan, bool reset)
   chan->channel.invite = (masklist *) calloc(1, sizeof(masklist));
   chan->channel.invite = (masklist *) calloc(1, sizeof(masklist));
   init_masklist(chan->channel.invite);
   init_masklist(chan->channel.invite);
 
 
-  chan->channel.member = (memberlist *) calloc(1, sizeof(memberlist));
+  chan->channel.member = new memberlist;
   chan->channel.member->nick[0] = 0;
   chan->channel.member->nick[0] = 0;
   chan->channel.member->next = NULL;
   chan->channel.member->next = NULL;
   chan->channel.topic = NULL;
   chan->channel.topic = NULL;
   chan->channel.floodtime = new bd::HashTable<bd::String, bd::HashTable<flood_t, time_t> >;
   chan->channel.floodtime = new bd::HashTable<bd::String, bd::HashTable<flood_t, time_t> >;
   chan->channel.floodnum  = new bd::HashTable<bd::String, bd::HashTable<flood_t, int> >;
   chan->channel.floodnum  = new bd::HashTable<bd::String, bd::HashTable<flood_t, int> >;
   chan->channel.cached_members = new bd::HashTable<bd::String, memberlist*>;
   chan->channel.cached_members = new bd::HashTable<bd::String, memberlist*>;
+  chan->channel.hashed_members = new bd::HashTable<RfcString, memberlist*>;
   /* Don't clear out existing roles, keep them until rebalancing
   /* Don't clear out existing roles, keep them until rebalancing
    * to not create a window of missing roles. */
    * to not create a window of missing roles. */
   if (!chan->bot_roles) {
   if (!chan->bot_roles) {
@@ -1046,21 +1047,17 @@ void clear_channel(struct chanset_t *chan, bool reset)
 
 
   if (chan->channel.cached_members) {
   if (chan->channel.cached_members) {
     if (chan->channel.cached_members->size()) {
     if (chan->channel.cached_members->size()) {
-      bd::Array<bd::String> member_uhosts(chan->channel.cached_members->keys());
-      for (size_t i = 0; i < member_uhosts.length(); ++i) {
-        const bd::String uhost(member_uhosts[i]);
-
+      for (const auto& uhost : chan->channel.cached_members->keys()) {
         // Delete the cached member
         // Delete the cached member
         m = (*chan->channel.cached_members)[uhost];
         m = (*chan->channel.cached_members)[uhost];
         delete_member(m);
         delete_member(m);
-
-        // Remove the cached member (not technically needed as it is deleted below, but for completeness.)
-        chan->channel.cached_members->remove(uhost);
       }
       }
     }
     }
     delete chan->channel.cached_members;
     delete chan->channel.cached_members;
     chan->channel.cached_members = NULL;
     chan->channel.cached_members = NULL;
   }
   }
+  delete chan->channel.hashed_members;
+  chan->channel.hashed_members = NULL;
 
 
   if (reset)
   if (reset)
     init_channel(chan, 1);
     init_channel(chan, 1);
@@ -1185,6 +1182,7 @@ int channel_add(char *result, const char *newname, char *options, bool isdefault
      * the server knows it, when we join the channel. <cybah>
      * the server knows it, when we join the channel. <cybah>
      */
      */
     strlcpy(chan->dname, newname, sizeof(chan->dname));
     strlcpy(chan->dname, newname, sizeof(chan->dname));
+    chanset_by_dname[chan->dname] = chan;
 
 
     /* Initialize chan->channel info */
     /* Initialize chan->channel info */
     if (isdefault) {
     if (isdefault) {

+ 1 - 0
src/mod/channels.mod/channels.cc

@@ -607,6 +607,7 @@ void remove_channel(struct chanset_t *chan)
      /* Remove the channel from the list, so that noone can pull it
      /* Remove the channel from the list, so that noone can pull it
         away from under our feet during the check_part() call. */
         away from under our feet during the check_part() call. */
      list_delete((struct list_type **) &chanset, (struct list_type *) chan);
      list_delete((struct list_type **) &chanset, (struct list_type *) chan);
+     chanset_by_dname.remove(chan->dname);
 
 
     /* Using chan->name is important here, especially for !chans <cybah> */
     /* Using chan->name is important here, especially for !chans <cybah> */
     if (!conf.bot->hub && shouldjoin(chan) && chan->name[0])
     if (!conf.bot->hub && shouldjoin(chan) && chan->name[0])

+ 11 - 11
src/mod/irc.mod/chan.cc

@@ -256,22 +256,16 @@ static memberlist *newmember(struct chanset_t *chan, char *nick)
 {
 {
   memberlist *x = chan->channel.member, 
   memberlist *x = chan->channel.member, 
              *lx = NULL, 
              *lx = NULL, 
-             *n = (memberlist *) calloc(1, sizeof(memberlist));
+             *n = new memberlist;
 
 
   /* This sorts the list */
   /* This sorts the list */
   while (x && x->nick[0] && (rfc_casecmp(x->nick, nick) < 0)) {
   while (x && x->nick[0] && (rfc_casecmp(x->nick, nick) < 0)) {
     lx = x;
     lx = x;
     x = x->next;
     x = x->next;
   }
   }
-  /*
-   * redundant as calloc is used
-   n->next = NULL;
-   n->split = 0L;
-   n->last = 0L;
-   n->delay = 0L;
-   */
 
 
   strlcpy(n->nick, nick, sizeof(n->nick));
   strlcpy(n->nick, nick, sizeof(n->nick));
+  n->rfc_nick = std::make_shared<RfcString>(n->nick);
   n->hops = -1;
   n->hops = -1;
   if (!lx) {
   if (!lx) {
     // Free the pseudo-member created in init_channel()
     // Free the pseudo-member created in init_channel()
@@ -290,13 +284,14 @@ static memberlist *newmember(struct chanset_t *chan, char *nick)
   ++(chan->channel.members);
   ++(chan->channel.members);
   n->floodtime = new bd::HashTable<flood_t, time_t>;
   n->floodtime = new bd::HashTable<flood_t, time_t>;
   n->floodnum  = new bd::HashTable<flood_t, int>;
   n->floodnum  = new bd::HashTable<flood_t, int>;
+  (*chan->channel.hashed_members)[*n->rfc_nick] = n;
   return n;
   return n;
 }
 }
 
 
 void delete_member(memberlist* m) {
 void delete_member(memberlist* m) {
   delete m->floodtime;
   delete m->floodtime;
   delete m->floodnum;
   delete m->floodnum;
-  free(m);
+  delete m;
 }
 }
 
 
 static bool member_getuser(memberlist* m, bool act_on_lookup) {
 static bool member_getuser(memberlist* m, bool act_on_lookup) {
@@ -3083,6 +3078,8 @@ static int gotnick(char *from, char *msg)
   if (auth)
   if (auth)
     auth->NewNick(msg);
     auth->NewNick(msg);
 
 
+  const RfcString rfc_nick(nick);
+  auto new_rfc_nick = std::make_shared<RfcString>(msg);
 
 
   /* Compose a nick!user@host for the new nick */
   /* Compose a nick!user@host for the new nick */
   simple_snprintf(s1, sizeof(s1), "%s!%s", msg, uhost);
   simple_snprintf(s1, sizeof(s1), "%s!%s", msg, uhost);
@@ -3091,7 +3088,7 @@ static int gotnick(char *from, char *msg)
   struct userrec *u = get_user_by_host(s1);
   struct userrec *u = get_user_by_host(s1);
 
 
   for (struct chanset_t *chan = chanset; chan; chan = chan->next) {
   for (struct chanset_t *chan = chanset; chan; chan = chan->next) {
-    m = ismember(chan, nick);
+    m = ismember(chan, rfc_nick);
 
 
     if (m) {
     if (m) {
       m->user = u;
       m->user = u;
@@ -3099,11 +3096,14 @@ static int gotnick(char *from, char *msg)
       /* Not just a capitalization change */
       /* Not just a capitalization change */
       if (rfc_casecmp(nick, msg)) {
       if (rfc_casecmp(nick, msg)) {
         /* Someone on channel with old nick?! */
         /* Someone on channel with old nick?! */
-	if ((mm = ismember(chan, msg)))
+	if ((mm = ismember(chan, *new_rfc_nick)))
 	  killmember(chan, mm->nick, false);
 	  killmember(chan, mm->nick, false);
       }
       }
 
 
+      chan->channel.hashed_members->remove(*m->rfc_nick);
       strlcpy(m->nick, msg, sizeof(m->nick));
       strlcpy(m->nick, msg, sizeof(m->nick));
+      m->rfc_nick = new_rfc_nick;
+      (*chan->channel.hashed_members)[*m->rfc_nick] = m;
       strlcpy(m->from, s1, sizeof(m->from));
       strlcpy(m->from, s1, sizeof(m->from));
 
 
       /*
       /*

+ 4 - 5
src/mod/irc.mod/irc.cc

@@ -1172,6 +1172,8 @@ killmember(struct chanset_t *chan, char *nick, bool cacheMember)
   else
   else
     chan->channel.member = x->next;
     chan->channel.member = x->next;
 
 
+  chan->channel.hashed_members->remove(*x->rfc_nick);
+
   if (cacheMember) {
   if (cacheMember) {
     x->last = now;
     x->last = now;
     x->user = NULL;
     x->user = NULL;
@@ -1199,11 +1201,8 @@ killmember(struct chanset_t *chan, char *nick, bool cacheMember)
     }
     }
     putlog(LOG_MISC, "*", "(!) actually I know of %d members.", chan->channel.members);
     putlog(LOG_MISC, "*", "(!) actually I know of %d members.", chan->channel.members);
   }
   }
-  if (unlikely(!chan->channel.member)) {
-    chan->channel.member = (memberlist *) calloc(1, sizeof(memberlist));
-    chan->channel.member->nick[0] = 0;
-    chan->channel.member->next = NULL;
-  }
+  if (unlikely(!chan->channel.member))
+    chan->channel.member = new memberlist;
   return 1;
   return 1;
 }
 }
 
 

+ 1 - 1
src/mod/server.mod/servmsg.cc

@@ -455,7 +455,7 @@ got005(char *from, char *msg)
       if (strcasecmp(p, "rfc1459")) {
       if (strcasecmp(p, "rfc1459")) {
         rfc_casecmp = strcasecmp;
         rfc_casecmp = strcasecmp;
         rfc_ncasecmp = strncasecmp;
         rfc_ncasecmp = strncasecmp;
-        rfc_toupper = toupper;
+        rfc_char_equal = char_equal;
       }
       }
     }
     }
   }
   }

+ 3 - 9
src/net.cc

@@ -161,7 +161,7 @@ void init_net()
 
 
 /* Get my ipv? ip
 /* Get my ipv? ip
  */
  */
-char *myipstr(int af_type)
+const char *myipstr(int af_type)
 {
 {
   if (cached_ip) {
   if (cached_ip) {
 #ifdef USE_IPV6
 #ifdef USE_IPV6
@@ -185,12 +185,6 @@ char *myipstr(int af_type)
   return "";
   return "";
 }
 }
 
 
-/* Get my ip number
- */
-in_addr_t getmyip() {
-  return cached_myip4_so.sin.sin_addr.s_addr;
-}
-
 /* see if it's necessary to set inaddr_any... because if we can't resolve, we die anyway */
 /* see if it's necessary to set inaddr_any... because if we can't resolve, we die anyway */
 void cache_my_ip()
 void cache_my_ip()
 {
 {
@@ -846,13 +840,13 @@ int open_listen_addr_by_af(const char *ip, in_port_t *port, int af_def)
 /* Returns the given network byte order IP address in the
 /* Returns the given network byte order IP address in the
  * dotted format - "##.##.##.##"
  * dotted format - "##.##.##.##"
  */
  */
-char *iptostr(in_addr_t ip)
+const char *iptostr(in_addr_t ip)
 {
 {
   static char ipbuf[32];
   static char ipbuf[32];
   struct in_addr a;
   struct in_addr a;
 
 
   a.s_addr = ip;
   a.s_addr = ip;
-  return (char *) inet_ntop(AF_INET, &a, ipbuf, sizeof(ipbuf));
+  return inet_ntop(AF_INET, &a, ipbuf, sizeof(ipbuf));
 }
 }
 
 
 /* Short routine to answer a connect received on a socket made previously
 /* Short routine to answer a connect received on a socket made previously

+ 13 - 8
src/net.h

@@ -101,9 +101,8 @@ typedef struct {
 
 
 # define killsock(x)     	real_killsock((x),__FILE__,__LINE__)
 # define killsock(x)     	real_killsock((x),__FILE__,__LINE__)
 
 
-unsigned long my_atoul(const char *);
-char *myipstr(int);
-in_addr_t getmyip();
+unsigned long my_atoul(const char *) __attribute__((pure));
+const char *myipstr(int);
 void cache_my_ip();
 void cache_my_ip();
 void setsock(int, int);
 void setsock(int, int);
 int allocsock(int, int);
 int allocsock(int, int);
@@ -117,11 +116,11 @@ int real_getsock(int, const char *, int);
 #endif /* USE_IPV6 */
 #endif /* USE_IPV6 */
 
 
 
 
-int sockprotocol(int);
+int sockprotocol(int) __attribute__((pure));
 void real_killsock(int, const char *, int);
 void real_killsock(int, const char *, int);
 int answer(int, char *, in_addr_t *, in_port_t *, int);
 int answer(int, char *, in_addr_t *, in_port_t *, int);
-int findanysnum(int);
-int findanyidx(int sock);
+int findanysnum(int) __attribute__((pure));
+int findanyidx(int sock) __attribute__((pure));
 int open_listen(in_port_t *);
 int open_listen(in_port_t *);
 int open_listen_by_af(in_port_t *, int);
 int open_listen_by_af(in_port_t *, int);
 int open_listen_addr_by_af(const char*, in_port_t *, int);
 int open_listen_addr_by_af(const char*, in_port_t *, int);
@@ -137,8 +136,8 @@ void tputs(int, const char *, size_t);
 void dequeue_sockets();
 void dequeue_sockets();
 int sockgets(char *, int *);
 int sockgets(char *, int *);
 void tell_netdebug(int);
 void tell_netdebug(int);
-char *iptostr(in_addr_t);
-bool sock_has_data(int, int);
+const char *iptostr(in_addr_t);
+bool sock_has_data(int, int) __attribute__((pure));
 int sockoptions(int sock, int operation, int sock_options);
 int sockoptions(int sock, int operation, int sock_options);
 void init_net(void);
 void init_net(void);
 int sock_read(bd::Stream&);
 int sock_read(bd::Stream&);
@@ -159,4 +158,10 @@ extern in_port_t				firewallport;
 extern jmp_buf				alarmret;
 extern jmp_buf				alarmret;
 extern sock_list			*socklist;
 extern sock_list			*socklist;
 
 
+static inline in_addr_t
+__attribute__((pure))
+getmyip() {
+  return cached_myip4_so.sin.sin_addr.s_addr;
+}
+
 #endif /* !_NET_H */
 #endif /* !_NET_H */

+ 2 - 1
src/response.h

@@ -25,9 +25,10 @@
 typedef const char* response_t;
 typedef const char* response_t;
 
 
 void init_responses();
 void init_responses();
-const char *response(response_t);
+const char *response(response_t) __attribute__((pure));
 
 
 inline const char *
 inline const char *
+__attribute__((pure))
 r_banned(struct chanset_t *chan)
 r_banned(struct chanset_t *chan)
 {
 {
   return response(RES_BANNED);
   return response(RES_BANNED);

+ 7 - 47
src/rfc1459.cc

@@ -27,18 +27,18 @@
 #include "common.h"
 #include "common.h"
 #include "rfc1459.h"
 #include "rfc1459.h"
 
 
-int (*rfc_casecmp) (const char *, const char *) = _rfc_casecmp;
-int (*rfc_ncasecmp) (const char *, const char *, size_t) = _rfc_ncasecmp;
-int (*rfc_toupper) (int) = _rfc_toupper;
+int (*rfc_casecmp) (const char *, const char *) __attribute__((pure)) = _rfc_casecmp;
+int (*rfc_ncasecmp) (const char *, const char *, size_t) __attribute__((pure)) = _rfc_ncasecmp;
+bool (*rfc_char_equal) (const char, const char) __attribute__((const)) = _rfc_char_equal;
 
 
 int
 int
 _rfc_casecmp(const char *s1, const char *s2)
 _rfc_casecmp(const char *s1, const char *s2)
 {
 {
-  while ((*s1) && (*s2) && (rfc_toupper(*s1) == rfc_toupper(*s2))) {
+  while ((*s1) && (*s2) && _rfc_char_equal(*s1, *s2)) {
     ++s1;
     ++s1;
     ++s2;
     ++s2;
   }
   }
-  return rfc_toupper(*s1) - rfc_toupper(*s2);
+  return _rfc_toupper(*s1) - _rfc_toupper(*s2);
 }
 }
 
 
 int
 int
@@ -46,51 +46,11 @@ _rfc_ncasecmp(const char *s1, const char *s2, size_t n)
 {
 {
   if (!n)
   if (!n)
     return 0;
     return 0;
-  while (--n && (*s1) && (*s2) && (rfc_toupper(*s1) == rfc_toupper(*s2))) {
+  while (--n && (*s1) && (*s2) && _rfc_char_equal(*s1, *s2)) {
     ++s1;
     ++s1;
     ++s2;
     ++s2;
   }
   }
-  return rfc_toupper(*s1) - rfc_toupper(*s2);
-}
-
-unsigned char rfc_touppertab[] = { 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
-  0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
-  0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
-  0x1e, 0x1f,
-  ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
-  '*', '+', ',', '-', '.', '/',
-  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
-  ':', ';', '<', '=', '>', '?',
-  '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
-  'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
-  'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
-  0x5f,
-  '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
-  'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
-  'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
-  0x7f,
-  0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
-  0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
-  0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
-  0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
-  0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
-  0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
-  0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
-  0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
-  0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
-};
-
-int
-_rfc_toupper(int c)
-{
-  return rfc_touppertab[(unsigned char) (c)];
+  return _rfc_toupper(*s1) - _rfc_toupper(*s2);
 }
 }
 
 
 /* vim: set sts=2 sw=2 ts=8 et: */
 /* vim: set sts=2 sw=2 ts=8 et: */

+ 58 - 6
src/rfc1459.h

@@ -1,12 +1,64 @@
 #ifndef _RFC1459_H
 #ifndef _RFC1459_H
 #define _RFC1459_H
 #define _RFC1459_H
 
 
-int _rfc_casecmp(const char *, const char *);
-int _rfc_ncasecmp(const char *, const char *, size_t);
-int _rfc_toupper(int);
+int _rfc_casecmp(const char *, const char *) __attribute__((pure));
+int _rfc_ncasecmp(const char *, const char *, size_t) __attribute__((pure));
 
 
-extern int (*rfc_casecmp) (const char *, const char *);
-extern int (*rfc_ncasecmp) (const char *, const char *, size_t);
-extern int (*rfc_toupper) (int);
+static const unsigned char rfc_touppertab[] = {
+  0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
+  0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
+  0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+  0x1e, 0x1f,
+  ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
+  '*', '+', ',', '-', '.', '/',
+  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+  ':', ';', '<', '=', '>', '?',
+  '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
+  'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
+  'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
+  0x5f,
+  '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
+  'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
+  'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
+  0x7f,
+  0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+  0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+  0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
+  0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
+  0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
+  0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
+  0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+  0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
+  0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static inline int __attribute__((const))
+_rfc_toupper(const int c)
+{
+  return rfc_touppertab[(unsigned char) (c)];
+}
+
+static inline bool __attribute__((const))
+char_equal(const char c1, const char c2)
+{
+  return c1 == c2;
+}
+
+static inline bool __attribute__((const))
+_rfc_char_equal(const char c1, const char c2)
+{
+  return _rfc_toupper(c1) == _rfc_toupper(c2);
+}
+
+extern bool (*rfc_char_equal) (const char, const char) __attribute__((const));
+extern int (*rfc_casecmp) (const char *, const char *) __attribute__((pure));
+extern int (*rfc_ncasecmp) (const char *, const char *, size_t) __attribute__((pure));
 
 
 #endif /* !_RFC1459_H */
 #endif /* !_RFC1459_H */

+ 4 - 2
src/set.cc

@@ -525,14 +525,16 @@ static int comp_variable_t(const void *m1, const void *m2) {
   return strcasecmp(mi1->name, mi2->name);
   return strcasecmp(mi1->name, mi2->name);
 }
 }
 
 
-static inline variable_t *var_get_var_by_name(const char *name)
+static inline variable_t * __attribute__((pure))
+var_get_var_by_name(const char *name)
 {
 {
   variable_t key;
   variable_t key;
   key.name = name;
   key.name = name;
   return (variable_t*) bsearch(&key, &vars, lengthof(vars) - 1, sizeof(variable_t), comp_variable_t);
   return (variable_t*) bsearch(&key, &vars, lengthof(vars) - 1, sizeof(variable_t), comp_variable_t);
 }
 }
 
 
-const char *var_get_gdata(const char *name) {
+const char * __attribute__((pure))
+var_get_gdata(const char *name) {
   variable_t* var = var_get_var_by_name(name);
   variable_t* var = var_get_var_by_name(name);
   return var && var->gdata ? var->gdata : NULL;
   return var && var->gdata ? var->gdata : NULL;
 }
 }

+ 1 - 1
src/set.h

@@ -87,7 +87,7 @@ void init_vars();
 void var_set_by_name(const char *, const char *, const char *);
 void var_set_by_name(const char *, const char *, const char *);
 void var_set_userentry(const char *, const char *, const char *);
 void var_set_userentry(const char *, const char *, const char *);
 const char *var_get_bot_data(struct userrec *u, const char *name, bool useDefault = false);
 const char *var_get_bot_data(struct userrec *u, const char *name, bool useDefault = false);
-const char *var_get_gdata(const char *name);
+const char *var_get_gdata(const char *name) __attribute__((pure));
 int cmd_set_real(const char *, int idx, char *);
 int cmd_set_real(const char *, int idx, char *);
 const char *var_get_str_by_name(const char *);
 const char *var_get_str_by_name(const char *);
 
 

+ 2 - 2
src/shell.cc

@@ -777,7 +777,7 @@ void werr(int errnum)
   exit(1); // This is never reached, done for gcc() warnings
   exit(1); // This is never reached, done for gcc() warnings
 }
 }
 
 
-char *homedir(bool useconf)
+const char *homedir(bool useconf)
 {
 {
   static char homedir_buf[PATH_MAX] = "";
   static char homedir_buf[PATH_MAX] = "";
 
 
@@ -793,7 +793,7 @@ char *homedir(bool useconf)
   return homedir_buf[0] ? homedir_buf : NULL;
   return homedir_buf[0] ? homedir_buf : NULL;
 }
 }
 
 
-char *my_username()
+const char *my_username()
 {
 {
   static char username[DIRMAX] = "";
   static char username[DIRMAX] = "";
 
 

+ 5 - 5
src/shell.h

@@ -48,8 +48,8 @@ namespace bd {
 void check_maxfiles();
 void check_maxfiles();
 void check_mypid();
 void check_mypid();
 void clear_tmp();
 void clear_tmp();
-char *homedir(bool = 1);
-char *my_username();
+const char *homedir(bool = 1);
+const char *my_username();
 void expand_tilde(char **);
 void expand_tilde(char **);
 int shell_exec(char *, char *, char **, char **, bool = 0);
 int shell_exec(char *, char *, char **, char **, bool = 0);
 int simple_exec(const char* argv[]);
 int simple_exec(const char* argv[]);
@@ -63,9 +63,9 @@ void crontab_create(int);
 void detected(int, const char *);
 void detected(int, const char *);
 void suicide(const char *);
 void suicide(const char *);
 void werr(int) __attribute__((noreturn));
 void werr(int) __attribute__((noreturn));
-const char *werr_tostr(int);
-int det_translate(const char *);
-const char *det_translate_num(int);
+const char *werr_tostr(int) __attribute__((const));
+int det_translate(const char *) __attribute__((pure));
+const char *det_translate_num(int) __attribute__((const));
 char *shell_escape(const char *);
 char *shell_escape(const char *);
 int mkdir_p(const char *);
 int mkdir_p(const char *);
 extern bool		clear_tmpdir;
 extern bool		clear_tmpdir;

+ 1 - 1
src/socket.cc

@@ -246,7 +246,7 @@ int socket_ip_to_uint(const char *ip, unsigned int *longip)
 }
 }
 
 
 #ifdef USE_IPV6
 #ifdef USE_IPV6
-static char hex_digits[] = {
+static const char hex_digits[] = {
         '0', '1', '2', '3', '4', '5', '6', '7',
         '0', '1', '2', '3', '4', '5', '6', '7',
         '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
         '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
 };
 };

+ 1 - 1
src/socket.h

@@ -40,7 +40,7 @@ int socket_get_name(int sock, char **ip, int *port);
 //int socket_get_peer_name(int sock, char **peer_ip, int *peer_port);
 //int socket_get_peer_name(int sock, char **peer_ip, int *peer_port);
 //int socket_get_error(int sock);
 //int socket_get_error(int sock);
 //int socket_accept(int sock, char **peer_ip, int *peer_port);
 //int socket_accept(int sock, char **peer_ip, int *peer_port);
-int is_dotted_ip(const char *ip);
+int is_dotted_ip(const char *ip) __attribute__((pure));
 int socket_ip_to_uint(const char *ip, unsigned int *longip);
 int socket_ip_to_uint(const char *ip, unsigned int *longip);
 int socket_ipv6_to_dots(const char *ip, char *dots);
 int socket_ipv6_to_dots(const char *ip, char *dots);
 
 

+ 2 - 2
src/tandem.h

@@ -73,8 +73,8 @@ void botnet_send_part_party(int, int, char *, int);
 void botnet_send_bye(const char *);
 void botnet_send_bye(const char *);
 void botnet_send_nkch_part(int, int, char *);
 void botnet_send_nkch_part(int, int, char *);
 void botnet_send_nkch(int, char *);
 void botnet_send_nkch(int, char *);
-int bots_in_subtree(tand_t *);
-int users_in_subtree(tand_t *);
+int bots_in_subtree(const tand_t *) __attribute__((pure));
+int users_in_subtree(const tand_t *) __attribute__((pure));
 int botnet_send_cmd(char * fbot, char * bot, char *fhnd, int fromidx, char * cmd);
 int botnet_send_cmd(char * fbot, char * bot, char *fhnd, int fromidx, char * cmd);
 void botnet_send_cmd_broad(int idx, char * fbot, char *fhnd, int fromidx, char * cmd);
 void botnet_send_cmd_broad(int idx, char * fbot, char *fhnd, int fromidx, char * cmd);
 void botnet_send_cmdreply(char * fbot, char * bot, char * to, char * toidx, char * ln);
 void botnet_send_cmdreply(char * fbot, char * bot, char * to, char * toidx, char * ln);

+ 1 - 1
src/userent.cc

@@ -1068,7 +1068,7 @@ bool add_entry_type(struct user_entry_type *type)
   return 1;
   return 1;
 }
 }
 
 
-struct user_entry_type *find_entry_type(char *name)
+struct user_entry_type *find_entry_type(const char *name)
 {
 {
   struct user_entry_type *p = NULL;
   struct user_entry_type *p = NULL;
 
 

+ 3 - 3
src/users.h

@@ -42,8 +42,8 @@ list_delete(struct list_type **h, struct list_type *i)
   return 0;
   return 0;
 }
 }
 
 
-static inline bool
-list_contains(struct list_type *h, struct list_type *i)
+static inline bool __attribute__((pure))
+list_contains(const struct list_type *h, const struct list_type *i)
 {
 {
   for (; h; h = h->next)
   for (; h; h = h->next)
     if (h == i) {
     if (h == i) {
@@ -120,7 +120,7 @@ struct filesys_stats {
 };
 };
 
 
 bool add_entry_type(struct user_entry_type *);
 bool add_entry_type(struct user_entry_type *);
-struct user_entry_type *find_entry_type(char *);
+struct user_entry_type *find_entry_type(const char *) __attribute__((pure));
 struct user_entry *find_user_entry(struct user_entry_type *, struct userrec *);
 struct user_entry *find_user_entry(struct user_entry_type *, struct userrec *);
 void *get_user(struct user_entry_type *, struct userrec *);
 void *get_user(struct user_entry_type *, struct userrec *);
 bool user_has_host(const char *, struct userrec *, char *);
 bool user_has_host(const char *, struct userrec *, char *);

Некоторые файлы не были показаны из-за большого количества измененных файлов