src/mem.c File Reference

#include "main.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "mod/modvals.h"
Include dependency graph for mem.c:

Go to the source code of this file.

Defines

#define MEMTBLSIZE   25000
#define COMPILING_MEM

Functions

int expected_memory ()
int expmem_chanprog ()
int expmem_misc ()
int expmem_fileq ()
int expmem_users ()
int expmem_dccutil ()
int expmem_botnet ()
int expmem_tcl ()
int expmem_tclhash ()
int expmem_tclmisc ()
int expmem_net ()
int expmem_modules ()
int expmem_language ()
int expmem_tcldcc ()
int expmem_dns ()
void init_mem ()
void tell_mem_status (char *nick)
void tell_mem_status_dcc (int idx)
void debug_mem_to_dcc (int idx)
char * n_strdup (const char *s, const char *file, int line)
void * n_malloc (int size, const char *file, int line)
void * n_realloc (void *ptr, int size, const char *file, int line)
void n_free (void *ptr, const char *file, int line)

Variables

module_entrymodule_list

Define Documentation

#define COMPILING_MEM

Definition at line 28 of file mem.c.

#define MEMTBLSIZE   25000

Definition at line 27 of file mem.c.

Referenced by init_mem(), tell_mem_status(), and tell_mem_status_dcc().


Function Documentation

void debug_mem_to_dcc ( int  idx  ) 

Definition at line 117 of file mem.c.

References dprintf, egg_strcasecmp, expmem_botnet(), expmem_chanprog(), expmem_dccutil(), expmem_dns(), expmem_language(), expmem_misc(), expmem_modules(), expmem_net(), expmem_tcl(), expmem_tcldcc(), expmem_tclhash(), expmem_tclmisc(), expmem_users(), _module_entry::funcs, MODCALL_EXPMEM, _module_entry::name, _module_entry::next, NULL, and tell_netdebug().

Referenced by cmd_debug().

00118 {
00119 #ifdef DEBUG_MEM
00120 #  define MAX_MEM 13
00121   unsigned long exp[MAX_MEM], use[MAX_MEM], l;
00122   int i, j;
00123   char fn[20], sofar[81];
00124   module_entry *me;
00125   char *p;
00126 
00127   exp[0] = expmem_language();
00128   exp[1] = expmem_chanprog();
00129   exp[2] = expmem_misc();
00130   exp[3] = expmem_users();
00131   exp[4] = expmem_net();
00132   exp[5] = expmem_dccutil();
00133   exp[6] = expmem_botnet();
00134   exp[7] = expmem_tcl();
00135   exp[8] = expmem_tclhash();
00136   exp[9] = expmem_tclmisc();
00137   exp[10] = expmem_modules(1);
00138   exp[11] = expmem_tcldcc();
00139   exp[12] = expmem_dns();
00140 
00141   for (me = module_list; me; me = me->next)
00142     me->mem_work = 0;
00143 
00144   for (i = 0; i < MAX_MEM; i++)
00145     use[i] = 0;
00146 
00147   for (i = 0; i < lastused; i++) {
00148     strcpy(fn, memtbl[i].file);
00149     p = strchr(fn, ':');
00150     if (p)
00151       *p = 0;
00152     l = memtbl[i].size;
00153     if (!strcmp(fn, "language.c"))
00154       use[0] += l;
00155     else if (!strcmp(fn, "chanprog.c"))
00156       use[1] += l;
00157     else if (!strcmp(fn, "misc.c"))
00158       use[2] += l;
00159     else if (!strcmp(fn, "userrec.c"))
00160       use[3] += l;
00161     else if (!strcmp(fn, "net.c"))
00162       use[4] += l;
00163     else if (!strcmp(fn, "dccutil.c"))
00164       use[5] += l;
00165     else if (!strcmp(fn, "botnet.c"))
00166       use[6] += l;
00167     else if (!strcmp(fn, "tcl.c"))
00168       use[7] += l;
00169     else if (!strcmp(fn, "tclhash.c"))
00170       use[8] += l;
00171     else if (!strcmp(fn, "tclmisc.c"))
00172       use[9] += l;
00173     else if (!strcmp(fn, "modules.c"))
00174       use[10] += l;
00175     else if (!strcmp(fn, "tcldcc.c"))
00176       use[11] += l;
00177     else if (!strcmp(fn, "dns.c"))
00178       use[12] += l;
00179     else if (p) {
00180       for (me = module_list; me; me = me->next)
00181         if (!strcmp(fn, me->name))
00182           me->mem_work += l;
00183     } else
00184       dprintf(idx, "Not logging file %s!\n", fn);
00185   }
00186 
00187   for (i = 0; i < MAX_MEM; i++) {
00188     switch (i) {
00189     case 0:
00190       strcpy(fn, "language.c");
00191       break;
00192     case 1:
00193       strcpy(fn, "chanprog.c");
00194       break;
00195     case 2:
00196       strcpy(fn, "misc.c");
00197       break;
00198     case 3:
00199       strcpy(fn, "userrec.c");
00200       break;
00201     case 4:
00202       strcpy(fn, "net.c");
00203       break;
00204     case 5:
00205       strcpy(fn, "dccutil.c");
00206       break;
00207     case 6:
00208       strcpy(fn, "botnet.c");
00209       break;
00210     case 7:
00211       strcpy(fn, "tcl.c");
00212       break;
00213     case 8:
00214       strcpy(fn, "tclhash.c");
00215       break;
00216     case 9:
00217       strcpy(fn, "tclmisc.c");
00218       break;
00219     case 10:
00220       strcpy(fn, "modules.c");
00221       break;
00222     case 11:
00223       strcpy(fn, "tcldcc.c");
00224       break;
00225     case 12:
00226       strcpy(fn, "dns.c");
00227       break;
00228     }
00229 
00230     if (use[i] == exp[i])
00231       dprintf(idx, "File '%-10s' accounted for %lu/%lu (ok)\n", fn, exp[i],
00232               use[i]);
00233     else {
00234       dprintf(idx, "File '%-10s' accounted for %lu/%lu (debug follows:)\n",
00235               fn, exp[i], use[i]);
00236       strcpy(sofar, "   ");
00237       for (j = 0; j < lastused; j++) {
00238         if ((p = strchr(memtbl[j].file, ':')))
00239           *p = 0;
00240         if (!egg_strcasecmp(memtbl[j].file, fn)) {
00241           if (p)
00242             sprintf(&sofar[strlen(sofar)], "%-10s/%-4d:(%04d) ",
00243                     p + 1, memtbl[j].line, memtbl[j].size);
00244           else
00245             sprintf(&sofar[strlen(sofar)], "%-4d:(%04d) ",
00246                     memtbl[j].line, memtbl[j].size);
00247 
00248           if (strlen(sofar) > 60) {
00249             sofar[strlen(sofar) - 1] = 0;
00250             dprintf(idx, "%s\n", sofar);
00251             strcpy(sofar, "   ");
00252           }
00253         }
00254         if (p)
00255           *p = ':';
00256       }
00257       if (sofar[0]) {
00258         sofar[strlen(sofar) - 1] = 0;
00259         dprintf(idx, "%s\n", sofar);
00260       }
00261     }
00262   }
00263 
00264   for (me = module_list; me; me = me->next) {
00265     Function *f = me->funcs;
00266     int expt = 0;
00267 
00268     if ((f != NULL) && (f[MODCALL_EXPMEM] != NULL))
00269       expt = f[MODCALL_EXPMEM] ();
00270     if (me->mem_work == expt)
00271       dprintf(idx, "Module '%-10s' accounted for %lu/%lu (ok)\n", me->name,
00272               expt, me->mem_work);
00273     else {
00274       dprintf(idx, "Module '%-10s' accounted for %lu/%lu (debug follows:)\n",
00275               me->name, expt, me->mem_work);
00276       strcpy(sofar, "   ");
00277       for (j = 0; j < lastused; j++) {
00278         strcpy(fn, memtbl[j].file);
00279         if ((p = strchr(fn, ':')) != NULL) {
00280           *p = 0;
00281           if (!egg_strcasecmp(fn, me->name)) {
00282             sprintf(&sofar[strlen(sofar)], "%-10s/%-4d:(%04X) ", p + 1,
00283                     memtbl[j].line, memtbl[j].size);
00284             if (strlen(sofar) > 60) {
00285               sofar[strlen(sofar) - 1] = 0;
00286               dprintf(idx, "%s\n", sofar);
00287               strcpy(sofar, "   ");
00288             }
00289             *p = ':';
00290           }
00291         }
00292       }
00293       if (sofar[0]) {
00294         sofar[strlen(sofar) - 1] = 0;
00295         dprintf(idx, "%s\n", sofar);
00296       }
00297     }
00298   }
00299 
00300   dprintf(idx, "--- End of debug memory list.\n");
00301 #else
00302   dprintf(idx, "Compiled without extensive memory debugging (sorry).\n");
00303 #endif
00304   tell_netdebug(idx);
00305 }

Here is the call graph for this function:

Here is the caller graph for this function:

int expected_memory (  ) 

Definition at line 202 of file main.c.

References expmem_botnet(), expmem_chanprog(), expmem_dccutil(), expmem_language(), expmem_misc(), expmem_modules(), expmem_net(), expmem_tcl(), expmem_tcldcc(), expmem_tclhash(), expmem_tclmisc(), and expmem_users().

00203 {
00204   int tot;
00205 
00206   tot = expmem_chanprog() + expmem_users() + expmem_misc() + expmem_dccutil() +
00207         expmem_botnet() + expmem_tcl() + expmem_tclhash() + expmem_net() +
00208         expmem_modules(0) + expmem_language() + expmem_tcldcc() +
00209         expmem_tclmisc();
00210   return tot;
00211 }

Here is the call graph for this function:

int expmem_botnet (  ) 

Definition at line 49 of file botnet.c.

References dcc_t::bot, from, maxparty, tand_t_struct::next, and parties.

Referenced by debug_mem_to_dcc(), and expected_memory().

00050 {
00051   int size = 0, i;
00052   tand_t *bot;
00053 
00054   for (bot = tandbot; bot; bot = bot->next)
00055     size += sizeof(tand_t);
00056   size += (maxparty * sizeof(party_t));
00057   for (i = 0; i < parties; i++) {
00058     if (party[i].away)
00059       size += strlen(party[i].away) + 1;
00060     if (party[i].from)
00061       size += strlen(party[i].from) + 1;
00062   }
00063   return size;
00064 }

Here is the caller graph for this function:

int expmem_chanprog (  ) 

Definition at line 216 of file chanprog.c.

References timer_str::cmd, and timer_str::next.

Referenced by debug_mem_to_dcc(), and expected_memory().

00217 {
00218   register int tot = 0;
00219   register tcl_timer_t *t;
00220 
00221   for (t = timer; t; t = t->next)
00222     tot += sizeof(tcl_timer_t) + strlen(t->cmd) + 1;
00223   for (t = utimer; t; t = t->next)
00224     tot += sizeof(tcl_timer_t) + strlen(t->cmd) + 1;
00225   return tot;
00226 }

Here is the caller graph for this function:

int expmem_dccutil (  ) 

Definition at line 97 of file dccutil.c.

References dcc_total, dcc_table::expmem, max_dcc, threaddata::MAXSOCKS, threaddata(), dcc_t::type, and dcc_t::u.

Referenced by debug_mem_to_dcc(), and expected_memory().

00098 {
00099   int tot, i;
00100 
00101   tot = sizeof(struct dcc_t) * max_dcc;
00102   tot += sizeof(sock_list) * threaddata()->MAXSOCKS;
00103 
00104   for (i = 0; i < dcc_total; i++) {
00105     if (dcc[i].type && dcc[i].type->expmem)
00106       tot += dcc[i].type->expmem(dcc[i].u.other);
00107   }
00108   return tot;
00109 }

Here is the call graph for this function:

Here is the caller graph for this function:

int expmem_dns (  ) 

Definition at line 515 of file dns.c.

References dnsevent_expmem().

Referenced by debug_mem_to_dcc().

00516 {
00517   return dnsevent_expmem();
00518 }

Here is the call graph for this function:

Here is the caller graph for this function:

int expmem_fileq (  ) 

Referenced by transfer_expmem().

Here is the caller graph for this function:

int expmem_language (  ) 

Definition at line 563 of file language.c.

References lang_pr::lang, lang_st::lang, lang_pr::next, lang_st::next, lang_t::next, lang_st::section, and lang_t::text.

Referenced by cmd_languagestatus(), debug_mem_to_dcc(), and expected_memory().

00564 {
00565   lang_tab *l;
00566   lang_sec *ls;
00567   lang_pri *lp;
00568   int i, size = 0;
00569 
00570   for (i = 0; i < 64; i++)
00571     for (l = langtab[i]; l; l = l->next) {
00572       size += sizeof(lang_tab);
00573       size += (strlen(l->text) + 1);
00574     }
00575   for (ls = langsection; ls; ls = ls->next) {
00576     size += sizeof(lang_sec);
00577     if (ls->section)
00578       size += strlen(ls->section) + 1;
00579     if (ls->lang)
00580       size += strlen(ls->lang) + 1;
00581   }
00582   for (lp = langpriority; lp; lp = lp->next) {
00583     size += sizeof(lang_pri);
00584     if (lp->lang)
00585       size += strlen(lp->lang) + 1;
00586   }
00587   return size;
00588 }

Here is the caller graph for this function:

int expmem_misc (  ) 

Definition at line 83 of file misc.c.

References help_ref::first, help_list, max_logs, help_list_t::next, and help_ref::next.

00084 {
00085   struct help_ref *current;
00086   struct help_list_t *item;
00087   int tot = 0;
00088 
00089   for (current = help_list; current; current = current->next) {
00090     tot += sizeof(struct help_ref) + strlen(current->name) + 1;
00091 
00092     for (item = current->first; item; item = item->next)
00093       tot += sizeof(struct help_list_t) + strlen(item->name) + 1;
00094   }
00095   return tot + (max_logs * sizeof(log_t));
00096 }

int expmem_modules (  ) 
int expmem_net (  ) 

Definition at line 90 of file net.c.

References threaddata::MAXSOCKS, NULL, SOCK_TCL, SOCK_UNUSED, and threaddata().

00091 {
00092   int i, tot = 0;
00093   struct threaddata *td = threaddata();
00094 
00095   for (i = 0; i < td->MAXSOCKS; i++) {
00096     if (!(td->socklist[i].flags & (SOCK_UNUSED | SOCK_TCL))) {
00097       if (td->socklist[i].handler.sock.inbuf != NULL)
00098         tot += strlen(td->socklist[i].handler.sock.inbuf) + 1;
00099       if (td->socklist[i].handler.sock.outbuf != NULL)
00100         tot += td->socklist[i].handler.sock.outbuflen;
00101     }
00102   }
00103   return tot;
00104 }

Here is the call graph for this function:

int expmem_tcl (  ) 

Definition at line 101 of file tcl.c.

References clientdata_stuff, strtot, and utftot.

00102 {
00103   return strtot + utftot + clientdata_stuff;
00104 }

int expmem_tcldcc (  ) 

Definition at line 48 of file tcldcc.c.

References portmap::next.

00049 {
00050   int tot = 0;
00051   struct portmap *pmap;
00052 
00053   for (pmap = root; pmap; pmap = pmap->next)
00054     tot += sizeof(struct portmap);
00055 
00056   return tot;
00057 }

int expmem_tclhash (  ) 

Definition at line 195 of file tclhash.c.

00196 {
00197   int tot = 0;
00198   tcl_bind_list_t *tl;
00199 
00200   for (tl = bind_table_list; tl; tl = tl->next)
00201     tot += tcl_bind_list_expmem(tl);
00202   return tot;
00203 }

int expmem_tclmisc (  ) 

Definition at line 59 of file tclmisc.c.

References max_logs, and NULL.

00060 {
00061   int i, tot = 0;
00062 
00063   for (i = 0; i < max_logs; i++) {
00064     if (logs[i].filename != NULL) {
00065       tot += strlen(logs[i].filename) + 1;
00066       tot += strlen(logs[i].chname) + 1;
00067     }
00068   }
00069 
00070   return tot;
00071 }

int expmem_users (  ) 

Definition at line 98 of file userrec.c.

References chanset_t::bans, userrec::chanrec, userrec::entries, chanset_t::exempts, user_entry_type::expmem, expmem_mask(), global_exempts, global_invites, igrec::igmask, chanuserrec::info, chanset_t::invites, user_entry::list, list_type_expmem(), igrec::msg, user_entry::name, igrec::next, chanset_t::next, user_entry::next, chanuserrec::next, userrec::next, NULL, user_entry::type, user_entry::u, and igrec::user.

00099 {
00100   int tot;
00101   struct userrec *u;
00102   struct chanuserrec *ch;
00103   struct chanset_t *chan;
00104   struct user_entry *ue;
00105   struct igrec *i;
00106 
00107   tot = 0;
00108   for (u = userlist; u; u = u->next) {
00109     for (ch = u->chanrec; ch; ch = ch->next) {
00110       tot += sizeof(struct chanuserrec);
00111 
00112       if (ch->info != NULL)
00113         tot += strlen(ch->info) + 1;
00114     }
00115     tot += sizeof(struct userrec);
00116 
00117     for (ue = u->entries; ue; ue = ue->next) {
00118       tot += sizeof(struct user_entry);
00119 
00120       if (ue->name) {
00121         tot += strlen(ue->name) + 1;
00122         tot += list_type_expmem(ue->u.list);
00123       } else
00124         tot += ue->type->expmem(ue);
00125     }
00126   }
00127   /* Account for each channel's masks */
00128   for (chan = chanset; chan; chan = chan->next) {
00129 
00130     /* Account for each channel's ban-list user */
00131     tot += expmem_mask(chan->bans);
00132 
00133     /* Account for each channel's exempt-list user */
00134     tot += expmem_mask(chan->exempts);
00135 
00136     /* Account for each channel's invite-list user */
00137     tot += expmem_mask(chan->invites);
00138   }
00139 
00140   tot += expmem_mask(global_bans);
00141   tot += expmem_mask(global_exempts);
00142   tot += expmem_mask(global_invites);
00143 
00144   for (i = global_ign; i; i = i->next) {
00145     tot += sizeof(struct igrec);
00146 
00147     tot += strlen(i->igmask) + 1;
00148     if (i->user)
00149       tot += strlen(i->user) + 1;
00150     if (i->msg)
00151       tot += strlen(i->msg) + 1;
00152   }
00153   return tot;
00154 }

Here is the call graph for this function:

void init_mem (  ) 

Definition at line 73 of file mem.c.

References MEMTBLSIZE, and NULL.

Referenced by main().

00074 {
00075 #ifdef DEBUG_MEM
00076   int i;
00077 
00078   for (i = 0; i < MEMTBLSIZE; i++)
00079     memtbl[i].ptr = NULL;
00080 #endif
00081 }

Here is the caller graph for this function:

void n_free ( void *  ptr,
const char *  file,
int  line 
)

Definition at line 395 of file mem.c.

References free, LOG_MISC, NULL, and putlog.

00396 {
00397   int i = 0;
00398 
00399   if (ptr == NULL) {
00400     putlog(LOG_MISC, "*", "*** ATTEMPTING TO FREE NULL PTR: %s (%d)",
00401            file, line);
00402     i = i;
00403     return;
00404   }
00405 #ifdef DEBUG_MEM
00406   /* Give tcl builtins an escape mechanism */
00407   if (line) {
00408     for (i = 0; (i < lastused) && (memtbl[i].ptr != ptr); i++);
00409     if (i == lastused) {
00410       putlog(LOG_MISC, "*", "*** ATTEMPTING TO FREE NON-MALLOC'D PTR: %s (%d)",
00411              file, line);
00412       return;
00413     }
00414     memused -= memtbl[i].size;
00415     lastused--;
00416     /* We don't want any holes, so if this wasn't the last entry, swap it. */
00417     if (i != lastused) {
00418       memtbl[i].ptr = memtbl[lastused].ptr;
00419       memtbl[i].size = memtbl[lastused].size;
00420       memtbl[i].line = memtbl[lastused].line;
00421       strcpy(memtbl[i].file, memtbl[lastused].file);
00422     }
00423   }
00424 #endif
00425   free(ptr);
00426 }

void* n_malloc ( int  size,
const char *  file,
int  line 
)

Definition at line 341 of file mem.c.

References fatal, LOG_MISC, malloc, NULL, and putlog.

Referenced by _get_data_ptr(), _user_malloc(), n_malloc_null(), and n_realloc().

00342 {
00343   void *x;
00344 
00345   x = (void *) malloc(size);
00346   if (x == NULL) {
00347     putlog(LOG_MISC, "*", "*** FAILED MALLOC %s (%d) (%d): %s", file, line,
00348            size, strerror(errno));
00349     fatal("Memory allocation failed", 0);
00350   }
00351 #ifdef DEBUG_MEM
00352   addtomemtbl(x, size, file, line);
00353 #endif
00354   return x;
00355 }

Here is the caller graph for this function:

void* n_realloc ( void *  ptr,
int  size,
const char *  file,
int  line 
)

Definition at line 357 of file mem.c.

References LOG_MISC, n_malloc(), NULL, and putlog.

Referenced by _user_realloc().

00358 {
00359   void *x;
00360   int i = 0;
00361 
00362 #ifdef DEBUG_MEM
00363   char *p;
00364 #endif
00365 
00366   /* ptr == NULL is valid. Avoiding duplicate code further down */
00367   if (!ptr)
00368     return n_malloc(size, file, line);
00369 
00370   x = (void *) realloc(ptr, size);
00371   if (x == NULL && size > 0) {
00372     i = i;
00373     putlog(LOG_MISC, "*", "*** FAILED REALLOC %s (%d)", file, line);
00374     return NULL;
00375   }
00376 #ifdef DEBUG_MEM
00377   for (i = 0; (i < lastused) && (memtbl[i].ptr != ptr); i++);
00378   if (i == lastused) {
00379     putlog(LOG_MISC, "*", "*** ATTEMPTING TO REALLOC NON-MALLOC'D PTR: %s (%d)",
00380            file, line);
00381     return NULL;
00382   }
00383   memused -= memtbl[i].size;
00384   memtbl[i].ptr = x;
00385   memtbl[i].line = line;
00386   memtbl[i].size = size;
00387   p = strrchr(file, '/');
00388   strncpy(memtbl[i].file, p ? p + 1 : file, 19);
00389   memtbl[i].file[19] = 0;
00390   memused += size;
00391 #endif
00392   return x;
00393 }

Here is the call graph for this function:

Here is the caller graph for this function:

char* n_strdup ( const char *  s,
const char *  file,
int  line 
)

Definition at line 329 of file mem.c.

References egg_strdup().

00330 {
00331   char *x;
00332 
00333   x = egg_strdup(s);
00334 /* compat strdup uses nmalloc itself */
00335 #if defined(DEBUG_MEM) && defined(HAVE_STRDUP)
00336   addtomemtbl(x, strlen(s)+1, file, line);
00337 #endif
00338   return x;
00339 }

Here is the call graph for this function:

void tell_mem_status ( char *  nick  ) 

Definition at line 85 of file mem.c.

References DP_HELP, dprintf, expected_memory, and MEMTBLSIZE.

00086 {
00087 #ifdef DEBUG_MEM
00088   float per;
00089 
00090   per = ((lastused * 1.0) / (MEMTBLSIZE * 1.0)) * 100.0;
00091   dprintf(DP_HELP, "NOTICE %s :Memory table usage: %d/%d (%.1f%% full)\n",
00092           nick, lastused, MEMTBLSIZE, per);
00093 #endif
00094   dprintf(DP_HELP, "NOTICE %s :Think I'm using about %dk.\n", nick,
00095           (int) (expected_memory() / 1024));
00096 }

void tell_mem_status_dcc ( int  idx  ) 

Definition at line 98 of file mem.c.

References dprintf, expected_memory, and MEMTBLSIZE.

Referenced by cmd_status(), and core_secondly().

00099 {
00100 #ifdef DEBUG_MEM
00101   int exp;
00102   float per;
00103 
00104   exp = expected_memory();      /* in main.c ? */
00105   per = ((lastused * 1.0) / (MEMTBLSIZE * 1.0)) * 100.0;
00106   dprintf(idx, "Memory table: %d/%d (%.1f%% full)\n", lastused, MEMTBLSIZE,
00107           per);
00108   per = ((exp * 1.0) / (memused * 1.0)) * 100.0;
00109   if (per != 100.0)
00110     dprintf(idx, "Memory fault: only accounting for %d/%ld (%.1f%%)\n",
00111             exp, memused, per);
00112   dprintf(idx, "Memory table itself occupies an additional %dk static\n",
00113           (int) (sizeof(memtbl) / 1024));
00114 #endif
00115 }

Here is the caller graph for this function:


Variable Documentation

Definition at line 186 of file modules.c.


Generated on 7 Sep 2016 for Eggdrop by  doxygen 1.6.1