Merge branch '0.74-penndev' into HEAD
authorRick L Bird <nveid@yahoo.com>
Sun, 10 Apr 2011 17:16:50 +0000 (13:16 -0400)
committerRick L Bird <nveid@yahoo.com>
Sun, 10 Apr 2011 17:16:50 +0000 (13:16 -0400)
Conflicts:
INSTALL
MANIFEST
MANIFEST.new
Makefile.SH
Patchlevel
README
UPGRADING
game/txt/hlp/cobra_chat.hlp
game/txt/hlp/cobra_func.hlp
hdrs/attrib.h
hdrs/flags.h
hdrs/version.h
src/Makefile.SH
src/attrib.c
src/bsd.c
src/command.c
src/conf.c
src/console.c
src/filecopy.c
src/flags.c
src/function.c
src/funlist.c
src/funstr.c
src/funtime.c
src/game.c
src/local.dst
src/lock.c
src/player.c
src/rplog.c
src/set.c
src/wild.c
utils/mkcmds.sh.SH
utils/mkvershlp.pl
utils/preparedist.sh

55 files changed:
1  2 
MANIFEST
Makefile.SH
game/mushcnf.dst
game/txt/hlp/cobra_chat.hlp
game/txt/hlp/cobra_cmd.hlp
game/txt/hlp/cobra_func.hlp
game/txt/hlp/cobratop.hlp
hdrs/attrib.h
hdrs/externs.h
hdrs/flags.h
hdrs/mushtype.h
hdrs/parse.h
options.h.dist
src/Makefile.SH
src/atr_tab.c
src/attrib.c
src/boolexp.c
src/bsd.c
src/cmds.c
src/command.c
src/conf.c
src/cque.c
src/db.c
src/destroy.c
src/division.c
src/extchat.c
src/extmail.c
src/filecopy.c
src/flags.c
src/function.c
src/fundb.c
src/funlist.c
src/funmisc.c
src/funstr.c
src/funtime.c
src/game.c
src/lock.c
src/look.c
src/move.c
src/notify.c
src/parse.c
src/player.c
src/predicat.c
src/prog.c
src/services.c
src/set.c
src/speech.c
src/sql.c
src/strutil.c
src/timer.c
src/unparse.c
src/utils.c
src/wild.c
src/wiz.c
utils/preparedist.sh

diff --cc MANIFEST
Simple merge
diff --cc Makefile.SH
index f0e7afb50d7b363552ae14036b7c22aa8b1c1fa2,da430218ce124b4f14356361cca027ec549c7c48..8a42ac7479059922c1cd977bf1d0efd8cf982ab4
@@@ -45,14 -45,11 +45,12 @@@ $spitshell >Makefile <<!GROK!THIS
  # If you want to profile the code, add -pg -a -DPROFILING to CCFLAGS
  # and (probably) remove -O
  #
- # If you want to do a less paranoid compile, remove the following from CCFLAGS:
- # -Wall -Wno-comment -Wno-parentheses -Wno-switch -Werror
- #
++
  $make_set_make
  CC=$cc
- CCFLAGS=$optimize -I.. -I../hdrs -Wall -Wno-comment -Wno-parentheses -Wno-switch -Werror $ccflags $warnings
+ CCFLAGS=$optimize -I.. -I../hdrs $ccflags $warnings -Wall -Wno-comment -Wno-parentheses -Wno-switch -Werror
  LDFLAGS=$ldflags
 -CLIBS=$libs $cryptlib $libssl $libcrypto $libmysqlclient
 +CLIBS=-lltdl $libs $cryptlib $libssl $libcrypto $libmysqlclient
  INSTALL=$install
  INSTALLDIR=$installdir
  CP=$cp
Simple merge
Simple merge
index 93af3918815f2f12f9f420faf386a1d6f4faf072,b51713d1c5d1b9945813eefe29a521a8cb48c6ca..8d6434f7e6e1d5ee89ba6ce6984a8af97c250263
@@@ -989,8 -994,8 +994,8 @@@ See also: SAFE, GOING, DESTROY_O
      This will do just the same as the above, except it will also create
      an exit named "Out <S>;s;south;out;o" coming back from the kitchen
      to whatever room you are currently in.
 -
 +    
- See also: @open, @link, EXITS, @create
+ See also: @open, @link, EXITS, @create, DBREF
  & @doing
    @doing <message>
    @doing/header <message>
@@@ -1948,10 -1930,12 +1930,12 @@@ See also: LISTENING, @ahear, @amhear, @
     @lock My Toy = = me
       This locks the object "My Toy" to you and you alone. It is recommended
       that you @lock me == me in order to prevent anyone else from picking
-      you up. The two = signs are NOT a typo!
+      you up. The two = signs are NOT a typo! The first is part of the @lock
+      syntax (as shown at the top of "help @lock") the second is a lock key
+      that means "exactly this object".
 -  
 +
-   You can lock an object -against- one other object as well, using the '!' 
-   symbol:
+   You can lock an object -against- another object as well, using the '!' 
+   symbol before any other key:
      @lock Shared Toy = !Vector Sigma
        This locks the object "Shared Toy" to everyone -except- Vector Sigma.
        Everyone except Vector will be able to pick up the object.
index 36886f8e7271bde0322a456ce103695268bbf259,71dc1408e346c8e6171cb8b3649eb81745db5c0d..549922d00e9fcbda3f89d3ee642453b5c204f1cf
    A list of available built-in functions can be obtained via the command
    "@config/functions". In the help text, the list is under the topic
    "FUNCTION LIST".
 -
 +  
    In addition to these built-in functions are MUSH-defined "global user
 -  functions."  These are defined by objects with the "GFuncs" power, via
 +  functions."  These are defined by objects with the "GFuncs" power, via 
    the "@function" command. To the user, they act just like the built-in g
    ame functions. For details on global user functions, see "help @function".
 -
 +  
    See also: MUSHCODE
  & FUNCTION LIST
    Several major variants of functions are available. The help topics
    The command "@config/functions" lists all of the game's built-in functions.
    The command "@function" lists all of the game's custom global functions
      defined via the @function command.
 -
 +  
  & Attribute functions
-   All these functions access attributes on an object.
+   The primary purpose of these functions is to access information
+   stored in attributes on objects.
 -
 -  aposs()       attrib_set()  default()     edefault()    eval()
 -  get()         grep()        grepi()       lattr()       nattr()
 -  obj()         poss()        regrep()      regrepi()     subj()
 -  udefault()    ufun()        uldefault()   ulocal()      v-function
 -  wildgrep()    wildgrepi()   xget()        zfun()
 +  
 +  aposs()       apply()       default()     edefault()    eval()
 +  filter()      filterbool()  fold()        foreach()     get()
 +  grep()        grepi()       lattr()       nattr()       obj()
 +  poss()        regrep()      regrepi()     subj()        udefault()
 +  ufun()        uldefault()   ulocal()      v-function    xget()
-   zfun()
++  zwildgrep()    wildgrepi()   xget()             fun()
  
  See also: ATTRIBUTES, NON-STANDARD ATTRIBUTES
+ See also: ATTRIBUTES, NON-STANDARD ATTRIBUTES
  & Bitwise functions
    These functions treat integers as a sequence of binary bits (Either 0
    or 1) and manipulate them.
@@@ -93,8 -94,8 +95,8 @@@
    and()         cand()        cor()         eq()          gt()
    gte()         lt()          lte()         nand()        neq()
    nor()         not()         or()          t()           xor()
 -
 +    
  See also: BOOLEAN VALUES, @config
+ See also: BOOLEAN VALUES, @config
  & Communication functions
    Communication functions are side-effect functions that send a message
    to an object or objects.
    on a game, or about specific connections.
  
    cmds()        conn()        doing()       height()      hostname()
 -  hidden()      idle()        ipaddr()      lports()      lwho()
 +  hidden()      idle()        ipaddr()      lports()      lwho()        
-   mwho()        ports()       pueblo()      recv()        sent()
-   ssl()         terminfo()    width()       idle_average() 
+   lwhoid()      mwho()        mwhoid()      nmwho()       nwho()
+   ports()       pueblo()      recv()        sent()        ssl()
+   terminfo()    width()       xmwho()       xmwhoid()     xwho()
+   xwhoid()      zmwho()       zwho()
  & Dbref functions
    Dbref functions return a dbref or list of dbrefs related to some value
    on an object.
 -
 -  children()    con()         entrances()   exit()        followers()
 -  following()   home()        lcon()        lexits()      loc()
 -  locate()      lparent()     lplayers()    lsearch()     lvcon()
 -  lvexits()     lvplayers()   namelist()    next()        nextdbref()
 -  num()         owner()       parent()      pmatch()      rloc()
 -  rnum()        room()        where()       zone()
 +  
 +  children()                con()                     entrances()
 +  exit()                    followers()               following()
 +  home()                    lcon()                    lexits()
 +  loc()                     locate()                  lparent()
 +  lplayers()                lsearch()                 lvcon()
 +  lvexits()                 lvplayers()               namelist()
 +  next()                    num()                     owner()
 +  parent()                  pmatch()                  rloc()
 +  rnum()                    room()                    where()
 +  zone()
  
  See also: DBREF
+ See also: DBREF
  & Information functions
    Information functions return values related to objects or the game.
 -
 + 
-   andflags()    andlflags()   config()      controls()    ctime()
-   elock()       findable()    flags()       fullname()    hasattr()
-   hasattrp()    hasflag()     haspower()    hastype()     iname()       
-   lflags()      lock()        lstats()      money()       mtime()
-   mudname()     name()        nattr()       nearby()      objid()
-   objmem()      orflags()     orlflags()    playermem()   poll()        
-   powers()      quota()       restarts()    type()        version()     
-   visible()     
+   alias()       andflags()    andlflags()   config()      controls()
+   ctime()       elock()       findable()    flags()       fullalias()
+   fullname()    hasattr()     hasattrp()    hasflag()     haspower()
+   hastype()     iname()       lflags()      lock()        lstats()
+   money()       mtime()       mudname()     name()        nattr()
+   nearby()      objid()       objmem()      orflags()     orlflags()
+   playermem()   poll()        powers()      quota()       restarts()
+   type()        version()     visible()
  
  & List functions
    List functions take at least one list of elements and return transformed
    can take an arbitrary <delimiter> argument to specify what delimits
    list elements; if none is provided, a space is used by default.
  
-   element()     elements()    extract()     first()       grab()
-   graball()     index()       insert()      itemize()     items()
-   iter()        last()        ldelete()     map()         match()
-   matchall()    member()      mix()         munge()       remove()
+   element()     elements()    extract()     filter()      filterbool()
+   first()       fold()        grab()        graball()     index()
+   insert()      itemize()     items()       iter()        last()
+   ldelete()     map()         match()       matchall()    member()
+   mix()         munge()       namegrab()    namegraball() remove()
    replace()     rest()        revwords()    setdiff()     setinter()
-   setunion()    shuffle()     sort()        sortby()      splice()
-   step()        table()       wordpos()     words()
+   setunion()    shuffle()     sort()        sortby()      sortkey()
+   splice()      step()        table()       unique()      wordpos()
+   words()
 -
 +    
  See also: LISTS
+ See also: LISTS
  & Math functions
    Math functions take one or more floating point numbers and return 
    a numeric value.
    regmatchi()   regrab()     regraball()    regraballi()  regrabi()
    regrep()      regrepi()    reswitch()     reswitchall() reswitchalli()
    reswitchi()
 -
 + 
  See also: string functions, regexp
+ See also: string functions, regexp
  & SQL functions
    These functions perform queries or other operations on an SQL
    database to which the MUSH is connected, if SQL support is
  & String functions
    String functions take at least one string and return a transformed
    string, parts of a string, or a value related to the string(s).
 -
 +  
-   accent()      after()       alphamin()    alphamax()    art()
-   before()      brackets()    capstr()      case()        caseall()
-   cat()         center()      comp()        chr()         decrypt()
-   delete()      digest()      edit()        encrypt()     escape()
-   if()          ifelse()      lcstr()       left()        lit()
-   ljust()       merge()       mid()         ord()         pos()
-   regedit()     lpos()        regmatch()    repeat()      reverse()
-   right()       rjust()       scramble()    secure()      sha0()
-   space()       spellnum()    squish()      strcat()      strinsert()
-   stripaccents()stripansi()   strlen()      strmatch()    strreplace()
-   switch()      trim()        ucstr()       wrap()
-  
-   See also: STRINGS
+   accent()      after()       align()       alphamin()    alphamax()
+   art()         before()      brackets()    capstr()      case()
+   caseall()     cat()         center()      comp()        chr()
+   decompose()   decrypt()     delete()      digest()      edit()
+   encrypt()     escape()      if()          ifelse()      foreach()
+   lcstr()       left()        lit()         ljust()       merge()
+   mid()         ord()         ordinal()     pos()         regedit()
+   lpos()        regmatch()    repeat()      reverse()     right()
+   rjust()       scramble()    secure()      sha0()        space()
+   spellnum()    squish()      strcat()      strinsert()   stripaccents()
+   stripansi()   strlen()      strmatch()    strreplace()  switch()
+   trim()        ucstr()       wrap()
+ See also: STRINGS
  & Time functions
    These functions return times or format times.
 -
 +  
    convsecs()    convutcsecs() convtime()    ctime()       etimefmt()
    isdaylight()  mtime()       restarttime() secs()        starttime()
 -  stringsecs()  time()        timefmt()     timestring()  utctime()
 +  stringsecs()  time()        timefmt()     timestring()  utctime()   
  
  & Utility functions
    These functions don't quite fit into any other category.
 -
 -  allof()       ansi()        atrlock()     beep()        checkpass()
 -  clone()       create()      die()         dig()         firstof()
 -  functions()   isdbref()     isint()       isnum()       isword()
 -  localize()    link()        list()        lnum()        null()
 -  numversion()  objeval()     open()        pcreate()     r-function
 -  rand()        s-function    scan()        set()         setq()
 -  setr()        soundex()     soundslike()  speak()       tel()
 -  textentries() textfile()    valid()       wipe()        @@()
 +  
 +  allof()       ansi()        atrlock()     atrmodtime()  beep()
 +  break()     checkpass()   clone()       create()      die()
 +  dig()         firstof()     functions()   isdbref()     isint()
 +  isnum()       isword()      localize()    link()        list()
 +  lnum()        null()        objeval()     open()        pcreate()
 +  r-function    rand()        s-function    scan()        set()
-   setq()        setr()        soundex()     soundslike()  tel()
-   textfile()    valid()       wipe()        @@()
++  setq()        setr()        soundex()     soundslike()  speak()
++  tel()               textentries() textfile()    valid()       wipe()
++  @@()
  
  & @@()
  & NULL()
@@@ -545,10 -560,10 +576,10 @@@ See also: BOOLEAN VALUES, or(), xor(), 
    attrib_set(me/foo,%0) will _always_ create an attribute.
  
    Of course, if the empty_attrs configuration option is turned off,
-   then the above paragraph doesn't apply.  See @config attribs.
+   then the above paragraph doesn't apply.  See '@config attribs'.
 -  
 +
  & BAND()
-   band(<integer>,<integers>,...)
+   band(<integer1>, <integer2>[, ... , <integerN>])
  
    Does a bitwise AND of all its arguments, returning the result
    (A number with only the bits set in every argument set in it).
   
    Sends <number> "alert" bell characters. <number> must be in the range
    1 to 5, or, if unspecified, defaults to 1.
 -  This function may only be used by 'Admin' type players. 
 +  This function may only be used by 'Admin' type players.
   
  & BEFORE()
    before(<string1>, <string2>)
@@@ -634,10 -653,10 +669,10 @@@ See also: strcat(
   
    Returns the least integral value greater than or equal to <number>.
  
  See also: floor(), bound(), round(), trunc()
+ See also: floor(), bound(), round(), trunc()
  & CENTER()
-   center(<string>,<width>[,<fill>[,<rightfill>]])
+   center(<string>, <width>[, <fill>[, <rightfill>]])
 - 
 +
    This function will center <string> within a field <width> characters wide,
    using the <fill> string for padding on the left side of the string,
    and <rightfill> for padding on the right side. <rightfill> defaults
  
    If <string> divides <width> into uneven portions, the left side
    will be one character shorter than the right side.
 - 
 +
-   Example:
+   Examples:
      > say center(X,5,-)
      You say, "--X--"
      > say center(X,5,-=)
@@@ -1414,15 -1432,8 +1448,8 @@@ Continued in HELP FOREACH
      > say [foreach(is_alphanum,jt1o+)]
      You say, "1 1 1 1 0 "
  
-   See also: anonymous attributes
-  
- & ACCNAME()
-   accname(<object>)
+ See also: anonymous attributes
 - 
 +
-   accname() returns the name of object <object>, applying the object's
-   @nameaccent, if any.
-   Related functions: NAME(), FULLNAME(), INAME()
  & FRACTION()
    fraction(<number>)
  
    extract(list, match(list, pattern, delimiter), 1, delimiter) or
    the regular expression variation thereof.
  
  See also: match(), extract(), element(), elements(), index(), regmatch(),
+ See also: match(), extract(), element(), elements(), index(), regmatch(),
 -  graball()
 +            graball()
  & GRABALL()
  & REGRABALL()
  & REGRABALLI()
@@@ -1519,12 -1530,12 +1546,12 @@@ See also: match(), matchall(), grab(), 
    names to search.
  
    Parsing _does_ occur before this function is invoked. Therefore,
 -  "special" characters will need to be escaped out. 
 +  "special" characters will need to be escaped out.
  
 -  grep()/wildgrep()/regrep() are case-sensitive. 
 +  grep()/wildgrep()/regrep() are case-sensitive.
    grepi()/wildgrepi()/regrepi() are case-insensitive.
  & GT()
-   gt(<num>,<num>)
+   gt(<num>, <num>)
  
    Takes two numbers, and returns 1 if and only if the first is greater
    than the second, and 0 otherwise.
@@@ -1966,20 -1994,17 +2010,22 @@@ See also: lcon(), exit(), next(), lvexi
      You say, "
      0foo---7
      01234567"
 -
 + 
+ See also: align(), center(), rjust()
  & LINK()
-   link(<name>, <destination> [, <preserve>])
+   link(<name>, <destination>[, <preserve>])
   
    This function links object <name> to <destination>. While normally
    used on exits, it has all of the other capabilities of @link as well.
-   It returns nothing.
+   It returns nothing. If the optional third argument is true, acts like 
+   @link/preserve.
  
 +  An optional boolean supplied third argument may given indicating 
 +  behavior similar to @link/preserve.
 +
    This is a side-effect function and may not be enabled on some MUSHes.
 +
 +  See Also: @link
  & LIST()
    list(<option>)
   
@@@ -2541,11 -2621,10 +2642,11 @@@ See also: anonymous attribute
    non-hidden players. It's exactly the same as lwho() used by a
    mortal, and is suitable for use on privileged global objects who
    need an unprivileged who-list.
 -  
 -  mwhoid() returns a list of objids instead.
 +
 +  mwhoid() gives a list of objids instead of dbrefs.
 +
  & ALIAS()
-   alias(<player>[,<new alias>])
+   alias(<player>[, <new alias>])
  
    Alias returns the alias of <player>. If multiple aliases are set,
    alias returns the first component of the alias.
  
    >"[namelist(#1 Javelin "ringo spar" bogus)]
    You say, "#1 #7 #56 #-1"
 -
 + 
  & NAMEGRAB()
  & NAMEGRABALL()
-   namegrab(<dbref list>,<name>)
-   namegraball(<dbref list>,<name>)
+   namegrab(<dbref list>, <name>)
+   namegraball(<dbref list>, <name>)
  
    The namegrab() function, when given a list of dbrefs and a name, returns
    the first dbref in the list that would match <name> as if you were
@@@ -2677,21 -2755,67 +2778,85 @@@ See also: and(), or(), nor(), xor(
  
    Returns the dbref number of the object, which must be in the same 
    room as the object executing num.
++
 +& NMWHO()
 +& NWHO()
 +  nwho()
 +  nmwho()
 +
 +  This returns a count of all currently-connected players. When
 +  mortals use this function, hidden players are NOT counted.
 +
 +  nmwho() returns a count of all currently connected, non-hidden players.
 +  It's exactly the same as nwho() used by a mortal, and is suitable for use
 +  on privileged global objects that always need an unprivileged count of
 +  who is online.
 +
 +  These functions are equivilent to words(lwho()) and words(mwho()),
 +  but are more efficient, and don't suffer from buffer constraints.
++=======
+ & NVCON()
+ & NCON()
+   ncon(<object>)
+   nvcon(<object>)
+   These functions return a count of the contents in a container.
+   ncon(<object>)  is identical to words(lcon(<object>))
+   nvcon(<object>) is identical to words(lvcon(<object>))
+ See also: nexits(), nplayers(), xcon(), lcon(), lvcon()
+ & NVEXITS()
+ & NEXITS()
+   nexits(<room>)
+   nvexits(<room>)
+   These functions return a count of the exits in a room.
+   nexits(<room>)  is identical to words(lexits(<room>))
+   nvexits(<room>) is identical to words(lvexits(<room>))
+ See also: ncon(), nplayers(), xexits(), lexits(), lvexits()
+ & NVPLAYERS()
+ & NPLAYERS()
+   nplayers(<object>)
+   nvplayers(<object>)
+   These functions return a count of the players in a container.
+   nplayers(<object>)  is identical to words(lplayers(<object>))
+   nvplayers(<object>) is identical to words(lvplayers(<object>))
+ See also: ncon(), nexits(), xplayers(), lplayers(), lvplayers()
+ & NVTHINGS()
+ & NTHINGS()
+   nthings(<object>)
+   nvthings(<object>)
+   These functions return a count of the things in a container.
+   nthings(<object>)  is identical to words(lthings(<object>))
+   nvthings(<object>) is identical to words(lvthings(<object>))
+ See also: ncon(), nexits(), xthings(), lthings(), lvthings()
+ & NMWHO()
+ & NWHO()
+   nwho()
+   nwho(<viewer>)
+   nmwho()
+   nwho() returns a count of all currently-connected players. When
+   mortals use this function, DARK wizards or royalty are NOT counted.
+   nmwho() returns a count of all currently connected, non-hidden players.
+   It's exactly the same as nwho() used by a mortal, and is suitable
+   for use on privileged global objects that always need an unprivileged
+   count of who is online.
+   If nwho() is given an argument, and is used by an object that can see
+   DARK and Hidden players, nwho() returns the count of online players
+   based on what <viewer> can see.
++>>>>>>> 0.74-penndev
  
  See also: lwho(), mwho(), xwho(), xmwho()
  & OBJ()
@@@ -2806,8 -2936,13 +2977,13 @@@ See also: BOOLEAN VALUES, and(
    the @pemit/list command. It returns nothing. It respects page-locks and
    HAVEN flags on players.
  
-   nspemit() is a privileged variation that works like @nspemit/list.
+   nspemit() is a wizard-only variation that works like @nspemit/list.
+   prompt() adds a telnet GOAHEAD to the end of the message, as per
+   the @prompt command. nsprompt() is a wizard-only variation that
+   works like @nsprompt.
 - 
 +  
+ See also: @prompt, @nsprompt, PROMPT_NEWLINES 
  & PI()
    pi()
    
@@@ -3041,9 -3184,10 +3225,10 @@@ See also: regrab(
    Example:
      > say [repeat(Test, 5)]
      You say, "TestTestTestTestTest"
 -
 +  
+ See also: space()
  & REPLACE()
-   replace(<list>,<position>,<new item>[,<single-character separator>])
+   replace(<list>, <position>, <new item>[,<single-character separator>])
    
    This replaces the item at <position> of <list> with <new item>.
    If no separator is given, a space is assumed. Null items are 
@@@ -3069,7 -3213,8 +3254,8 @@@ See also: after(), first(), last(
    Example:
      > say revwords(foo bar baz eep)
      You say, "eep baz bar foo"
 -
 +  
+ See also: flip()  
  & RIGHT()
    right(<string>, <length>)
  
@@@ -3092,7 -3238,8 +3279,8 @@@ See also: left(), mid(
      You say, "
      0---foo7
      01234567"
 -
 + 
+ See also: align(), center(), ljust()
  & RLOC()
    rloc(<object>, <levels>) 
    
@@@ -3231,9 -3380,10 +3421,10 @@@ See also: decompose(), escape(
    Example:
      > say setdiff(foo baz gleep bar, bar moof gleep)
      You say, "baz foo"
 -
 + 
+ See also: setinter(), setunion()
  & SETINTER()
-   setinter(<list1>, <list2>[, <delimiter>][, <sort type>][,<osep>])
+   setinter(<list1>, <list2>[,<delimiter>[, <sort type>[,<osep>]]])
   
    This function returns the intersection of two sets -- i.e., the
    elements that are in both <list1> and <list2>. The list that is
@@@ -3267,10 -3419,10 +3460,10 @@@ See also: setdiff(), setunion(
    storing complex function evaluations which are used repeatedly within
    a single command.
  
 -  Registers set via setq() or setr() can be accessed via the r() function,
 +  Registers set via setq() or setr() can be accessed via the r() function, 
    or via the %qN percent-substitution.
  
-   See "help SETQ2" for examples of its use.
+   See 'SETQ2' for examples of its use.
  
  & SETQ2
  
@@@ -3353,7 -3508,8 +3549,8 @@@ See also: setdiff(), setinter(
    This function shuffles the order of the items of a list, returning a
    random permutation of its elements. "[shuffle(foo bar baz gleep)]" 
    might evaluate to "baz foo gleep bar".
 -
 +  
+ See also: scramble()
  & SIGN()
    sign(<number>)
  
    numbers, it will sort them in order of smallest to largest. If all
    the words are dbrefs, it will sort them in order of smallest to
    largest. Otherwise, it will perform a lexicographic sort.
 -
 +  
-   The following letters as a second argument specify a certain sort:
-  
-   a:  Sort lexicographically (Maybe case-sensitive).
-   i:  Sort lexicographically (Always case-insensitive).
-   d:  Sort dbrefs.
-   n:  Sort integer numbers.
-   f:  Sort decimal numbers.
-   Whether or not the a sort type is case-sensitive or not depends
-   on the particular mush and its environment.
+   The second argument is a sort type. See 'help sorting'.
 - 
 +  
    The optional third argument gives the list's delimiter character.
    If not present, <delimiter> defaults to a space.
    The optional fourth argument gives a string that will delimit
@@@ -3621,9 -3802,11 +3837,10 @@@ See also: repeat(
    Wizard mutters: "Hello there."
    OR
    Wizard mutters something.
 - 
 +
    Continued in 'help Speak7'.
 - 
  & SPEAK7
+   
    Here's another example, where words between + signs are reversed,
    but those within double-quotes are untouched (demonstrating a technique
    useful in something where you want to allow users to mix ordinary speech
@@@ -3664,10 -3848,11 +3882,11 @@@ See also: spellnum(
      > say [splice(foo bar baz,eek moof gleep,bar)]
      You say, "foo moof baz"
  
+ See also: merge()
  & MAPSQL()
-   mapsql([<object>/]<attribute>,query[, <osep>[, <dofieldnames>])
+   mapsql([<object>/]<attribute>, <query>[, <osep>[, <dofieldnames>]])
  
 -  Performs an SQL query if the MUSH is configured to connect to an 
 +  Performs an SQL query if the MUSH is configured to connect to an
    SQL database server. This function requires a WIZARD flag or
    the Sql_Ok power.
  
@@@ -3837,7 -4025,9 +4059,9 @@@ See also: cat(
    > think strinsert(barbaz, 0, foo)
    foobarbaz
    > think strinsert(Myname, 2, %b)
 -  My name
 +  My name   
+ See also: strdelete()
  & STRIPACCENTS()
    stripaccents(<string>)
  
@@@ -4352,26 -4569,27 +4603,45 @@@ See also: u(), udefault(), ulocal(), se
    %q0, this is what was printed. In the first example, ulocal() reset the
    value of %q0 to its original "are delicious!"
   
-   See also: u(), setq(), r()
+ See also: u(), setq(), r()
+ & UNIQUE()
+   unique(<list>[, <sort type>[,<sep>[, <osep>]]])
+   unique() returns a copy of <list> with consecutive duplicate items
+   removed. It does not sort the list. The optional <sort type> describes
+   what type of data is in the list; see 'help sorting' for details. If
+   no type is given, the elements are compared as strings. The optional
+   third and fourth arguments are the list delimiter and output seperator.
+   Examples:
+   > think unique(a b b c b)
+     a b c b
+   > think unique(1 2 2.0 3, f)
+     1 2 3
+   > think unique(1|2|3|3, n, |, _)
+     1_2_3
+ See also: setunion()
  
 + & UNIQUE()
 +  unique(<list>[, <sort type>[,<sep>[, <osep>]]])
 +
 +  unique() returns a copy of <list> with consecutive duplicate items
 +  removed. It does not sort the list. The optional <sort type> describes
 +  what type of data is in the list; see 'help sorting' for details. If
 +  no type is given, the elements are compared as strings. The optional
 +  third and fourth arguments are the list delimiter and output seperator.
 +
 +  Examples:
 +  > think unique(a b b c b)
 +    a b c b
 +  > think unique(1 2 2.0 3, f)
 +    1 2 3
 +  > think unique(1|2|3|3, n, |, _)
 +    1_2_3
 +
 +
  & V()
  & V-FUNCTION
    V(<name of attribute>)
@@@ -4609,32 -4848,122 +4901,141 @@@ See also: nattr(), lattr(
    on the use of this function.
    
  & XOR()
-   xor(<boolean value>,<boolean value>)
+   xor(<boolean value 1>, <boolean value 2>[, ... , <boolean value N>])
+   Takes two or more booleans and returns a 1 if one, and only one, of
+   the inputs is equivalent to true(1).
+ See also: BOOLEAN VALUES, and(), or(), not(), nor()
+ & XVCON()
+ & XCON()
+   xcon(<object>, <start>, <count>)
+   xvcon(<object>, <start>, <count>)
+   xcon() fetches <count> or fewer item dbrefs from <object>'s contents
+   starting at position <start>. It is useful when the number of objects
+   in a container causes lcon() to exceed the buffer limit.
+   It is equivalent to extract(lcon(<object>),<start>,<count>)
+   xvcon() is identical, except it follows the restrictions of
+   lvcon()
+ See also: ncon(), lcon(), lvcon()
+ & XVEXITS()
+ & XEXITS()
+   xexits(<room>, <start>, <count>)
+   xvexits(<room>, <start>, <count>)
+   xexits() fetches <count> or fewer exit dbrefs from <room>
+   starting at position <start>. It is useful when the number
+   of exits in a container causes lexits() to exceed the buffer
+   limit.
+   It is equivalent to extract(lexits(<room>),<start>,<count>)
+   xvexits() is identical, except it follows the restrictions of
+   lvexits()
+ See also: nexits(), lexits(), lvexits()
+ & XVPLAYERS()
+ & XPLAYERS()
+   xplayers(<object>, <start>, <count>)
+   xvplayers(<object>, <start>, <count>)
+   xplayers() fetches <count> or fewer player dbrefs from <object>
+   starting at position <start>. It is useful when the number of
+   players in a container causes lplayers() to exceed the buffer limit.
+   It is equivalent to extract(lplayers(<object>),<start>,<count>)
+   xvplayers() is identical, except it follows the restrictions of
+   lvplayers()
+ See also: nplayers(), lplayers(), lvplayers()
+ & XVTHINGS()
+ & XTHINGS()
+   xthings(<object>, <start>, <count>)
+   xvthings(<object>, <start>, <count>)
+   xthings() fetches <count> or fewer non-player dbrefs from <object>'s
+   contents starting at position <start>. It is useful when the number of
+   players in a container causes lthings() to exceed the buffer limit.
+   It is equivalent to extract(lthings(<object>),<start>,<count>)
+   xvthings() is identical, except it follows the restrictions of
+   lvthings()
+ See also: nthings(), lthings(), lvthings()
+ & XWHO()
+ & XWHOID()
+ & XMWHO()
+ & XMWHOID()
+   xwho(<start>, <count>)
+   xmwho(<start>, <count>)
+   xwhoid(<start>, <count>)
+   xmwhoid(<start>, <count>)
+   xwho() fetches <count> or fewer player dbrefs from the list of connected
+   players. It is useful when the number of players connected causes lwho()
+   or pemits in +who $-commands to exceed buffer limits.
+   It is equivalent to extract(lwho(),<start>,<count>).
+   xmwho() is identical, except it is limited to non-DARK and non-HIDE
+   players.
+   xwhoid() and xmwhoid() return objids instead of dbrefs.
+ See also: lwho(), mwho(), nwho()
+ & ZMWHO()
+   zmwho(<object>)
+   This returns a list of the dbref numbers for all current-connected,
+   non-hidden players within a location belonging to the specified zone.
+   It's exactly the same as zwho() used by a mortal, and is suitable for
+   use on privileged global objects who need an unprivileged zwho-list.
+   The viewer must either have see_all privileges or pass the zone
+   lock of the zone to use the function.
+ See also: zwho()
+ & ZWHO()
+   zwho(<object>[, <viewer>])
+   This returns a list of the dbref numbers for all currently-connected
+   players within a location belonging to the specified zone. When mortals
+   use this function, the dbref numbers of DARK wizards or hidden royalty
+   do NOT appear on the dbref list. The viewer must either have see_all
+   privileges or pass the zone lock of the zone to use the function.
 -  
 +
-   Takes two booleans, and returns a 1 if one, and only one of the two
-   inputs is equivalent to true(1).  See BOOLEAN VALUES.
+   If <viewer> is given by a privileged user, zwho() returns a dbref list
+   using <viewer>'s privileges.
  
 -See also: zmwho()
 +  See also: and(), or(), not(), nor()
 +& XWHO()
 +  xwho(<start>, <count>)
 +  xmwho(<start>, <count>)
 +  xwhoid(<start>, <count>)
 +  xmwhoid(<start>, <count>)
 +
 +  xwho() fetches <count> or fewer player dbrefs from the list of connected
 +  players. It is useful when the number of players connected causes lwho()
 +  or pemits in +who $-commands to exceed buffer limits.
 +
 +  It is equivalent to extract(lwho(),<start>,<count>).
 +
 +  xmwho() is identical, except it is limited to non-DARK and non-HIDE
 +  players.
 +
 +  xwhoid() and xmwhoid() return objids instead of dbrefs.
 +
 +See also: lwho(), mwho(), nwho()
 +
  & ZEMIT()
+ & NSZEMIT()
    zemit(<zone>, <message>)
    nszemit(<zone>, <message>)
  
index 863e1623aec46a84b145c04a2004697af398ccdb,cdb579574c8c9987cb96128a67770e8e31444499..968ff295f9fcd20ffc1b8a1320b963dd9a945dcf
@@@ -680,9 -682,9 +682,9 @@@ See also: @lock, @fail, @efail, @lfai
    is in the SEX attribute is not recognizable, the MUSH will assume 
    the object is neuter. Setting a gender attribute will enable 
    pronoun substitution by the MUSH. The SEX attribute is visual to
 -  anyone who wants to see it.
 +  anyone who wants to see it. 
  
  See also: @sex, SUBSTITUTION
+ See also: @sex, SUBSTITUTION
  & GLOBALS
  & GLOBAL COMMANDS
    A command is "global" if it can be used anywhere in the world of the
diff --cc hdrs/attrib.h
index ee5d2283375218ae3c42f781f18bb33fd552949e,6c00b3355dc4a8cdf5edc71ed5bc843480175dda..c3234f4466530ebddbee64a791524df1b76fc387
   */
  
  struct attr {
 -  char const *name;           /**< Name of attribute */
 +  char const *name;             /**< Name of attribute */
-   int flags;                    /**< Attribute flags */
+   unsigned int flags;                 /**< Attribute flags */
 -  chunk_reference_t data;     /**< The attribute's value, compressed */
 -  dbref creator;              /**< The attribute's creator's dbref */
 -  boolexp write_lock;         /**< Attribute lock set */
 -  boolexp read_lock;          /**< Attribute read lock */
 -  time_t last_modified;               /**< Timestamp of last modification */
 -  ATTR *next;                 /**< Pointer to next attribute in list */
 +  chunk_reference_t data;       /**< The attribute's value, compressed */
 +  dbref creator;                /**< The attribute's creator's dbref */
 +  boolexp write_lock;           /**< Attribute lock set */
 +  boolexp read_lock;            /**< Attribute read lock */
 +  time_t last_modified;         /**< Timestamp of last modification */
 +  ATTR *next;                   /**< Pointer to next attribute in list */
  };
  
  struct aget_oi {
@@@ -56,9 -75,9 +75,9 @@@ extern ATTR *atr_get(dbref thing, char 
  extern ATTR *atr_get_noparent(dbref thing, char const *atr);
  typedef int (*aig_func) (dbref, dbref, dbref, const char *, ATTR *, void *);
  extern int atr_iter_get(dbref player, dbref thing, char const *name,
 -                      int mortal, aig_func func, void *args);
 +                        int mortal, aig_func func, void *args);
  extern ATTR *atr_complete_match(dbref player, char const *atr, dbref privs);
- extern void atr_free(dbref thing);
+ extern void atr_free_all(dbref thing);
  extern void atr_cpy(dbref dest, dbref source);
  extern char const *convert_atr(int oldatr);
  extern int atr_comm_match(dbref thing, dbref player, int type, int end,
@@@ -90,33 -109,42 +109,42 @@@ safe_atr_value(ATTR *atr
  
  
  /* possible attribute flags */
 -#define AF_ODARK        0x1   /* OBSOLETE! Leave here but don't use */
 -#define AF_INTERNAL     0x2   /* no one can see it or set it */
 -#define AF_PRIVILEGE    0x4   /* Only privileged players can change it */
 -#define AF_NUKED        0x8   /* OBSOLETE! Leave here but don't use */
 -#define AF_LOCKED       0x10  /* Only creator of attrib can change it. */
 -#define AF_NOPROG       0x20  /* won't be searched for $ commands. */
 -#define AF_MDARK        0x40  /* Only admins can see it */
 -#define AF_PRIVATE      0x80  /* Children don't inherit it */
 -#define AF_NOCOPY       0x100 /* atr_cpy (for @clone) doesn't copy it */
 -#define AF_VISUAL       0x200 /* Everyone can see this attribute */
 -#define AF_REGEXP       0x400 /* Match $/^ patterns using regexps */
 -#define AF_CASE         0x800 /* Match $/^ patterns case-sensitive */
 -#define AF_SAFE         0x1000        /* This attribute may not be modified */
+ #define AF_EMPTY_FLAGS  0x0   /**< No flag at all */
- #define AF_STATIC       0x10000 /* OBSOLETE! Leave here but don't use */
 +#define AF_ODARK        0x1     /* OBSOLETE! Leave here but don't use */
 +#define AF_INTERNAL     0x2     /* no one can see it or set it */
 +#define AF_PRIVILEGE    0x4     /* Only privileged players can change it */
 +#define AF_NUKED        0x8     /* OBSOLETE! Leave here but don't use */
 +#define AF_LOCKED       0x10    /* Only creator of attrib can change it. */
 +#define AF_NOPROG       0x20    /* won't be searched for $ commands. */
 +#define AF_MDARK        0x40    /* Only admins can see it */
 +#define AF_PRIVATE      0x80    /* Children don't inherit it */
 +#define AF_NOCOPY       0x100   /* atr_cpy (for @clone) doesn't copy it */
 +#define AF_VISUAL       0x200   /* Everyone can see this attribute */
 +#define AF_REGEXP       0x400   /* Match $/^ patterns using regexps */
 +#define AF_CASE         0x800   /* Match $/^ patterns case-sensitive */
 +#define AF_SAFE         0x1000  /* This attribute may not be modified */
 -#define AF_COMMAND      0x20000       /* INTERNAL: value starts with $ */
 -#define AF_LISTEN       0x40000       /* INTERNAL: value starts with ^ */
 -#define AF_NODUMP       0x80000       /* INTERNAL: attribute is not saved */
 -#define AF_LISTED       0x100000      /* INTERNAL: Used in @list attribs */
 -#define AF_PREFIXMATCH  0x200000      /* Subject to prefix-matching */
 -#define AF_VEILED       0x400000      /* On ex, show presence, not value */
 -#define AF_DEBUG      0x800000  /* Show debug when evaluated */
 -#define AF_NEARBY     0x1000000 /* Override AF_VISUAL if remote */
 -#define AF_PUBLIC     0x2000000 /* Override SAFER_UFUN */
 -#define AF_ANON               0x4000000 /* INTERNAL: Attribute doesn't exist in the database */
 -#define AF_POWINHERIT 0x8000000       /* Execute with powers of object it's on */
+ #define AF_ROOT         0x10000       /* Root of an attribute tree */
 -#define AF_MHEAR      0x20000000    /* ^-listens can be triggered by %! */
 -#define AF_AHEAR      0x40000000    /* ^-listens can be triggered by anyone */
 +#define AF_COMMAND      0x20000 /* INTERNAL: value starts with $ */
 +#define AF_LISTEN       0x40000 /* INTERNAL: value starts with ^ */
 +#define AF_NODUMP       0x80000 /* INTERNAL: attribute is not saved */
 +#define AF_LISTED       0x100000        /* INTERNAL: Used in @list attribs */
 +#define AF_PREFIXMATCH  0x200000        /* Subject to prefix-matching */
 +#define AF_VEILED       0x400000        /* On ex, show presence, not value */
 +#define AF_DEBUG        0x800000  /* Show debug when evaluated */
 +#define AF_NEARBY       0x1000000 /* Override AF_VISUAL if remote */
 +#define AF_PUBLIC       0x2000000 /* Override SAFER_UFUN */
 +#define AF_ANON         0x4000000 /* INTERNAL: Attribute doesn't exist in the database */
 +#define AF_POWINHERIT   0x8000000       /* Execute with powers of object it's on */
+ #define AF_NONAME       0x10000000    /**< No name in did_it */
 +#define AF_MHEAR        0x20000000    /* ^-listens can be triggered by %! */
 +#define AF_AHEAR        0x40000000    /* ^-listens can be triggered by anyone */
+ #define AF_NOSPACE      0x80000000    /**< No space in did_it */
+ #define AF_MAXVAL       0x100000000   /**< Largest attribute flag value. */
+ /*** external predefined attributes. */
+     extern ATTR attr[];
+  
  
  /* external predefined attributes. */
      extern ATTR attr[];
  #define AL_CREATOR(alist)       ((alist)->creator)
  #define AL_FLAGS(alist)         ((alist)->flags)
  #define AL_DEREFS(alist)        ((alist)->data?chunk_derefs((alist)->data):0)
 -#define AL_WLock(alist)               ((alist)->write_lock)
 -#define AL_RLock(alist)               ((alist)->read_lock)
 -#define AL_MODTIME(alist)     ((alist)->last_modified)
 +#define AL_WLock(alist)         ((alist)->write_lock)
 +#define AL_RLock(alist)         ((alist)->read_lock)
 +#define AL_MODTIME(alist)       ((alist)->last_modified)
  
- /* Errors from ok_player_alias */
+ /** Errors from ok_player_alias */
+ /** Success */
  #define OPAE_SUCCESS    1
+ /** Invalid alias */
  #define OPAE_INVALID    -1
+ /** Too many aliases already set */
  #define OPAE_TOOMANY    -2
+ /** Null alias */
  #define OPAE_NULL       -3
  
  #endif                          /* __ATTRIB_H */
diff --cc hdrs/externs.h
index 0a96c07d1e4d7c8e622ee969478bda53a01af7de,6d8681f0456c70c90a33f27a1be97bbc8f971117..1302f2c727a8d6f9f3d0d91dfa6f62f38e937a9b
@@@ -530,11 -531,12 +531,12 @@@ extern int safe_ansi_string2(ansi_strin
      extern int safe_fill(char x, size_t n, char *buff, char **bp);
  /* Append an accented string */
      extern int safe_accent(const char *RESTRICT base,
 -                         const char *RESTRICT tmplate, size_t len, char *buff,
 -                         char **bp);
 +                           const char *RESTRICT tmplate, size_t len, char *buff,
 +                           char **bp);
  
     extern char *str_escaped_chr(const char *RESTRICT string, char escape_chr);
 -   extern char *replace_string
+    extern char *mush_strncpy(char *restrict, const char *, size_t);
 +    extern char *replace_string
        (const char *RESTRICT old, const char *RESTRICT newbit,
         const char *RESTRICT string) __attribute_malloc__;
      extern char *replace_string2(const char *old[2], const char *newbits[2],
diff --cc hdrs/flags.h
index c196b3f3a508ee6704b85bf9f76c0740e9dde8e9,10d470fa64f67dd197888a6eea670086b16c407f..7ac19a957136e240c58027f5bccc8932ab5b073b
@@@ -133,19 -133,29 +133,27 @@@ extern void decompile_flags(dbref playe
   * Flag permissions
   */
  
 -#define F_ANY           0x10  /* can be set by anyone - obsolete now */
 -#define F_OWNED         0x40  /* can be set on owned objects */
 -#define F_PRIVILEGE   0x80    /* can only be set by privileged players */
 -#define F_GOD           0x200 /* can only be set by God */
 -#define F_INTERNAL      0x400 /* only the game can set this */
 -#define F_DARK          0x800 /* only God can see this flag */
 -#define F_MDARK         0x1000        /* admin/God can see this flag */
 -#define F_ODARK         0x2000        /* owner/admin/God can see this flag */
 -#define F_DISABLED      0x4000        /* flag can't be used */
 +#define F_ANY           0x10    /* can be set by anyone - obsolete now */
 +#define F_OWNED         0x40    /* can be set on owned objects */
 +#define F_PRIVILEGE     0x80    /* can only be set by privileged players */
 +#define F_GOD           0x200   /* can only be set by God */
 +#define F_INTERNAL      0x400   /* only the game can set this */
 +#define F_DARK          0x800   /* only God can see this flag */
 +#define F_MDARK         0x1000  /* admin/God can see this flag */
 +#define F_ODARK         0x2000  /* owner/admin/God can see this flag */
 +#define F_DISABLED      0x4000  /* flag can't be used */
- /* RESERVED             0x8000 */
- #define F_SELF          0x10000 /* can set on self, regardless of the above */
+ #define F_LOG         0x8000
+ #define F_SELF                0x10000 /* can set on self, regardless of the above */
+ /* Flags can be in the flaglist multiple times, thanks to aliases. Keep
+  *    a reference count of how many times, and free memory when it goes to 0. */
+ #define F_REF_MASK      0xFF000000 /**< Mask to get the reference count */
+ #define F_REF_NOT       0x00FFFFFF /**< Everything but */
+ #define FLAG_REF(r)     (((r) & F_REF_MASK) >> 30)
+ #define ZERO_FLAG_REF(r) ((r) & F_REF_NOT)
+ #define INCR_FLAG_REF(r) (ZERO_FLAG_REF((r)) | (((r) & F_REF_MASK) + (1 << 30)))
+ #define DECR_FLAG_REF(r) (ZERO_FLAG_REF((r)) | (((r) & F_REF_MASK) - (1 << 30)))
  
 -
 -
  /* we don't use these anymore.. but kept aroudn for DB conversion */
  
  /*--------------------------------------------------------------------------
diff --cc hdrs/mushtype.h
Simple merge
diff --cc hdrs/parse.h
Simple merge
diff --cc options.h.dist
Simple merge
diff --cc src/Makefile.SH
index a5d985f8d76014b662b47ce8989acd479a106d1a,488824345f95499b7a2bed9f7a2ac59aa733872e..c5e20d8a79518fbf6b74fdd4bda13a44778a16c5
@@@ -60,14 -59,14 +60,14 @@@ CFLAGS=$(CCFLAGS) $(RDEFS) $(IDEFS
  
  # List of C files, used for make depend:
  C_FILES=access.c atr_tab.c attrib.c boolexp.c bsd.c bufferq.c \
 -      chunk.c cmdlocal.c cmds.c \
 +      chunk.c  cmds.c \
        command.c compress.c conf.c cque.c create.c cron.c db.c destroy.c  division.c extchat.c \
 -      extmail.c filecopy.c flaglocal.c flags.c funcrypt.c function.c \
 -      fundb.c fundiv.c funlist.c funlocal.c funmath.c funmisc.c funstr.c funtime.c \
 -      funufun.c game.c help.c htab.c ident.c local.c lock.c log.c look.c \
 -      malias.c match.c memcheck.c move.c mycrypt.c mymalloc.c mysocket.c \
 +      extmail.c filecopy.c  flags.c funcrypt.c function.c \
 +      fundb.c fundiv.c funlist.c funmath.c funmisc.c funstr.c funtime.c \
 +      funufun.c game.c help.c htab.c ident.c lock.c log.c look.c \
 +      malias.c match.c memcheck.c move.c modules.c mushlua.c mushlua_wrap.c mycrypt.c mymalloc.c mysocket.c \
        myssl.c notify.c parse.c pcre.c player.c plyrlist.c \
-       predicat.c privtab.c prog.o ptab.c rob.c rplog.c services.c set.c shs.c  \
+       predicat.c privtab.c prog.o ptab.c rob.c services.c set.c shs.c  \
        sig.c speech.c sql.c strdup.c strtree.c  strutil.c tables.c timer.c unparse.c  \
        utils.c version.c warnings.c  wild.c wiz.c
  
@@@ -158,7 -198,7 +158,6 @@@ etags
  ctags: 
        ctags *.c 
  
- depend: 
 -depend: funlocal.c cmdlocal.c local.c flaglocal.c
        makedepend -fMakefile.SH -w10 -- -I../hdrs -I.. $(CFLAGS) -- $(C_FILES) $(H_FILES)
        perl ../utils/fixdepend.pl Makefile.SH
  
diff --cc src/atr_tab.c
Simple merge
diff --cc src/attrib.c
index 33818468ac8a3718891d1b3b1d920b29820720e4,5cf215a7a4746a8eaca260013c73e7978f8fb8c4..e6435fd1cfbfc647f1a04ebc77c47ed1c25f916c
@@@ -377,7 -369,8 +378,8 @@@ atrflag_to_string(int mask
   * \param player the player trying to do the write.
   * \param obj the object targetted for the write.
   * \param atr the attribute being interrogated.
 - * \param flags the default flags to add to the attribute. 
 + * \param flags the default flags to add to the attribute.
+  *              0 for default flags if it's a builtin attribute.
   * \retval 0 if the player cannot write the attribute.
   * \retval 1 if the player can write the attribute.
   */
@@@ -420,9 -414,16 +423,16 @@@ can_create_attr(dbref player, dbref obj
        AL_NAME(atr) = missing_name;
        set_default_flags(atr, flags, lock_owner, ns_chk);
        if(lock_owner == NOTHING)
 -      lock_owner = AL_CREATOR(atr);
 +        lock_owner = AL_CREATOR(atr);
        num_new++;
      }
+     /* Only GOD can create an AF_NODUMP attribute (used for semaphores)
+      * or add a leaf to a tree with such an attribute
+      */
+     if ((AL_FLAGS(atr) & AF_NODUMP) && (player != GOD)) {
+       missing_name[0] = '\0';
+       return AE_ERROR;
+     }
      if (Cannot_Write_This_Attr(player, atr, obj, 1, ns_chk, lock_owner)) {
        free_atr_locks(atr);
        missing_name[0] = '\0';
@@@ -731,59 -766,79 +775,79 @@@ real_atr_clr(dbref thing, char const *a
      return AE_ERROR;
    }
  
-   sub = atr_sub_branch(ptr);
-   if (!we_are_wiping && sub) {
+   if ((AL_FLAGS(ptr) & AF_ROOT) && !we_are_wiping) {
      ooref = tooref;
-     return AE_ERROR;
+     return AE_TREE;
    }
  
-   if (!IsPlayer(thing) && !AF_Nodump(ptr)) {
-     char lmbuf[1024];
-     ModTime(thing) = mudtime;
-     snprintf(lmbuf, 1023, "%s[#%d]", ptr->name, player);
-     lmbuf[strlen(lmbuf) + 1] = '\0';
-     set_lmod(thing, lmbuf);
-   }
-   *prev = AL_NEXT(ptr);
+   /* We only hit this if wiping. */
+   if (AL_FLAGS(ptr) & AF_ROOT)
+     can_clear = atr_clear_children(player, thing, ptr);
  
-   if (ptr->data)
-     chunk_delete(ptr->data);
+   if (can_clear) {
+     char *p;
+     char root_name[ATTRIBUTE_NAME_LIMIT + 1];
  
-   len = strlen(AL_NAME(ptr));
-   st_delete(AL_NAME(ptr), &atr_names);
+     strcpy(root_name, AL_NAME(ptr));
  
-   free_atr_locks(ptr);
-   AL_NEXT(ptr) = atr_free_list;
-   AL_FLAGS(ptr) = 0;
-   atr_free_list = ptr;
-   AttrCount(thing)--;
-   if (we_are_wiping && sub) {
-     while (*prev != sub)
-       prev = &AL_NEXT(*prev);
-     ptr = *prev;
-     while (ptr && strlen(AL_NAME(ptr)) > len && AL_NAME(ptr)[len] == '`') {
+    if (!IsPlayer(thing) && !AF_Nodump(ptr))
+      ModTime(thing) = mudtime;
 -   *prev = AL_NEXT(ptr);
 +      *prev = AL_NEXT(ptr);
-       if (ptr->data)
-         chunk_delete(ptr->data);
-       st_delete(AL_NAME(ptr), &atr_names);
-       AL_NEXT(ptr) = atr_free_list;
-       AL_FLAGS(ptr) = 0;
-       atr_free_list = ptr;
-       AttrCount(thing)--;
-       ptr = *prev;
+    atr_free_one(ptr);
+    AttrCount(thing)--;
 - 
++
+    /* If this was the only leaf of a tree, clear the AF_ROOT flag from
+     * the parent. */
+    if ((p = strrchr(root_name, '`'))) {
+      ATTR *root;
+      *p = '\0';
 -  
++
+      root = find_atr_in_list(List(thing), root_name);
+      *p = '`';
 -  
++
+      if (!root) {
+       do_rawlog(LT_ERR, T("Attribute %s on object #%d lacks a parent!"),
+                 root_name, thing);
+      } else {
+       if (!atr_sub_branch(root))
+         AL_FLAGS(root) &= ~AF_ROOT;
 -     }
 -   }
 +    }
 +  }
-   ooref = tooref;
-   return 1;
+   
+    return AE_OKAY;
+  } else
+    return AE_TREE;
  }
  
- /** Retrieve an attribute from an object or its ancestors.
+ /* Remove an attribute from an object.
+  * This function clears an attribute from an object. 
+  * Permission is denied if the attribute is a branch, not a leaf.
+  * \param thing object to clear attribute from.
+  * \param atr name of attribute to remove.
+  * \param player enactor attempting to remove attribute.
+  * \return AE_OKAY or an AE_* error code
+  */
+ atr_err
+ atr_clr(dbref thing, char const *atr, dbref player)
+ {
+  return real_atr_clr(thing, atr, player, 0);
+ }
+   
+   
+ /* \@wipe an attribute (And any leaves) from an object.
+  * This function clears an attribute from an object. 
+  * \param thing object to clear attribute from.
+  * \param atr name of attribute to remove.
+  * \param player enactor attempting to remove attribute.
+  * \return AE_OKAY or an AE_* error code.
+  */
+ atr_err
+ wipe_atr(dbref thing, char const *atr, dbref player)
+ {
+  return real_atr_clr(thing, atr, player, 1);
+ }
 - 
++
+  /** Retrieve an attribute from an object or its ancestors.
   * This function retrieves an attribute from an object, or from its
   * parent chain, returning a pointer to the first attribute that
   * matches or NULL. This is a pointer to an attribute structure, not
@@@ -1593,8 -1664,11 +1673,11 @@@ atr_comm_divmatch(dbref thing, dbref pl
          if (quick_wild_new(tbuf2 + 1, str, AF_Case(ptr))) {
            match_found = 1;
            match++;
-           wild_match_case(tbuf2 + 1, str, AF_Case(ptr));
+         if(!just_match)
+           wild_match_case_r(tbuf2 + 1, str, AF_Case(ptr),
+                             global_eval_context.wnxt, 10,
+                             match_space, match_space_len);
 -      }
 +        }
        }
        if (match_found) {
          /* Since we're still checking the lock on the child, not the
@@@ -1836,16 -1916,28 +1925,28 @@@ do_set_atr(dbref thing, const char *RES
    was_listener = Listener(thing);
    res =
        s ? atr_add(thing, name, s, player,
-                   (flags & 0x02) ? AF_NOPROG : NOTHING)
+                   (flags & 0x02) ? AF_NOPROG : AF_EMPTY_FLAGS)
        : atr_clr(thing, name, player);
-   if (res == AE_SAFE) {
+   switch (res) {
+   case AE_SAFE:
      notify_format(player, T("Attribute %s is SAFE. Set it !SAFE to modify it."),
 -                name);
 +                  name);
      return 0;
-   } else if (res == AE_BADNAME) {
-     notify(player, T("That's not a very good name for an attribute."));
+   case AE_TREE:
+     if (!s) {
+       notify_format(player,
+                   T("Unable to remove '%s' because of a protected tree attribute."),
+                   name);
+       return 0;
+     } else {
+       notify_format(player,
+                   T("Unable to set '%s' because of a failure to create a needed parent attribute."), name);
+       return 0;
+     }
+   case AE_BADNAME:
+     notify_format(player, T("That's not a very good name for an attribute."));
      return 0;
-   } else if (res == AE_ERROR) {
+   case AE_ERROR:
      if (*missing_name) {
        if (s && (EMPTY_ATTRS || *s))
          notify_format(player, T("You must set %s first."), missing_name);
diff --cc src/boolexp.c
Simple merge
diff --cc src/bsd.c
index 0e4aebe894288e32213e75821388fd73e39b03dc,5ce7127c72e616226126d32afee89ce996a3bc64..5f732ad5e8bb8f2085fbc822a0204df5ea329c32
+++ b/src/bsd.c
  #include <floatingpoint.h>
  #endif
  #include <locale.h>
- #ifdef __APPLE__
- #define LC_MESSAGES     6
- #define AUTORESTART
- #endif
  #include <setjmp.h>
 +#include <ltdl.h>
  
  #include "conf.h"
  
@@@ -420,8 -413,9 +419,10 @@@ static void promote_info_slave(void)
  static void query_info_slave(int fd);
  static void reap_info_slave(void);
  void kill_info_slave(void);
+ sig_atomic_t slave_error = 0;
+ #endif
  #endif
 +#endif
  void reopen_logs(void);
  void load_reboot_db(void);
  #ifdef HAS_GETRLIMIT
@@@ -513,9 -503,9 +514,11 @@@ main(int argc, char **argv
    fpsetmask(0L);
  #endif
  
+   options.mem_check = 1;
    time(&mudtime);
 +  /* Initialize Module interface */
 +  modules_init();
  
    /* If we have setlocale, call it to set locale info
     * from environment variables
@@@ -1175,44 -1183,44 +1205,59 @@@ shovechars(Port_t port, Port_t sslport 
  #endif
  #endif /* COMPILE_CONSOLE */
        for (d = descriptor_list; d; d = dnext) {
 -      dnext = d->next;
 +        dnext = d->next;
  #ifdef COMPILE_CONSOLE
 -      if (d->descriptor == 0) {
 -        input_ready = FD_ISSET(STDIN_FILENO, &input_set);
 -        output_ready = FD_ISSET(STDOUT_FILENO, &output_set);
 -      } else {
 -        input_ready = FD_ISSET(d->descriptor, &input_set);
 -        output_ready = FD_ISSET(d->descriptor, &output_set);
 -      }
 -      if (input_ready) {
 -        if (!process_input(d, output_ready)) {
 -          shutdownsock(d);
 -          if(d->descriptor == 0)
 -            return;
 -          continue;
 -        }
 -      }
 -      if (output_ready) {
 -        if (!process_output(d)) {
 -          shutdownsock(d);
 -          if (d->descriptor == 0)
 -            return;
 -        }
 -      }
 +        if (d->descriptor == 0) {
 +          input_ready = FD_ISSET(STDIN_FILENO, &input_set);
 +          output_ready = FD_ISSET(STDOUT_FILENO, &output_set);
 +        } else {
 +          input_ready = FD_ISSET(d->descriptor, &input_set);
 +          output_ready = FD_ISSET(d->descriptor, &output_set);
 +        }
 +        if (input_ready) {
 +          if (!process_input(d, output_ready)) {
 +            shutdownsock(d);
 +            if(d->descriptor == 0)
 +              return;
 +            continue;
 +          }
 +        }
 +        if (output_ready) {
 +          if (!process_output(d)) {
 +            shutdownsock(d);
 +            if (d->descriptor == 0)
 +              return;
 +          }
 +        }
 +#else /* COMPILE_CONSOLE */
 +        input_ready = FD_ISSET(d->descriptor, &input_set);
 +        output_ready = FD_ISSET(d->descriptor, &output_set);
 +        if (input_ready) {
 +          if (!process_input(d, output_ready)) {
 +            shutdownsock(d);
 +            continue;
 +          }
 +        }
 +        if (output_ready) {
 +          if (!process_output(d)) {
 +            shutdownsock(d);
 +          }
+ #else /* COMPILE_CONSOLE */
+       input_ready = FD_ISSET(d->descriptor, &input_set);
+       output_ready = FD_ISSET(d->descriptor, &output_set);
+       if (input_ready) {
+         if (!process_input(d, output_ready)) {
+           shutdownsock(d);
+           continue;
+         }
+       }
+       if (output_ready) {
+         if (!process_output(d)) {
+           shutdownsock(d);
+         }
+       }
++#endif /* COMPILE_CONSOLE */
 +        }
  #endif /* COMPILE_CONSOLE */
        }
      }
@@@ -1491,9 -1499,9 +1536,9 @@@ logout_sock(DESC *d
        d->unidle_times++;
      }
      snprintf(tbuf1, BUFFER_LEN-1, "%ld %ld %d %d", (mudtime - d->connected_at),
 -      d->idle_total, d->unidle_times, d->cmds); 
 +        d->idle_total, d->unidle_times, d->cmds); 
      tbuf1[strlen(tbuf1)+1] = '\0';
-     (void) atr_add(d->player, "LASTACTIVITY", tbuf1, GOD, NOTHING);
+     (void) atr_add(d->player, "LASTACTIVITY", tbuf1, GOD, 0);
      announce_disconnect(d->player);
  #ifdef USE_MAILER
      do_mail_purge(d->player);
@@@ -1571,13 -1579,13 +1616,13 @@@ shutdownsock(DESC *d
        fcache_dump(d, fcache.quit_fcache, NULL);
        /* Player was not allowed to log in from the connect screen */
        if(d->last_time > 0) {
 -      d->idle_total += difftime(mudtime, d->last_time);
 -      d->unidle_times++;
 +        d->idle_total += difftime(mudtime, d->last_time);
 +        d->unidle_times++;
        }
        snprintf(tbuf1, BUFFER_LEN-1, "%ld %ld %d %d", (mudtime - d->connected_at), 
 -        d->idle_total , d->unidle_times, d->cmds);
 +          d->idle_total , d->unidle_times, d->cmds);
        tbuf1[strlen(tbuf1)+1] = '\0';
-       (void) atr_add(d->player, "LASTACTIVITY", tbuf1, GOD, NOTHING);
+       (void) atr_add(d->player, "LASTACTIVITY", tbuf1, GOD, 0);
        announce_disconnect(d->player);
  #ifdef USE_MAILER
        do_mail_purge(d->player);
@@@ -2932,10 -2937,10 +2977,10 @@@ dump_messages(DESC *d, dbref player, in
  
    if (ModTime(player))
      notify_format(player, T("%ld failed connections since last login."),
-                   ModTime(player));
+                 (long) ModTime(player));
    ModTime(player) = (time_t) 0;
 -  announce_connect(player, isnew, num);       /* broadcast connect message */
 -  check_last(player, d->addr, d->ip); /* set Last, Lastsite, give paycheck */
 +  announce_connect(player, isnew, num); /* broadcast connect message */
 +  check_last(player, d->addr, d->ip);   /* set Last, Lastsite, give paycheck */
    /* Check folder 0, not silently (i.e. Report lack of mail, too) */
    queue_eol(d);
  #ifdef USE_MAILER
@@@ -4801,18 -4812,30 +4861,30 @@@ inactivity_check(void
    unconnected_idle = UNCONNECTED_LIMIT ? UNCONNECTED_LIMIT : INT_MAX;
    for (d = descriptor_list; d; d = nextd) {
      nextd = d->next;
-     idle_for = now - d->last_time;
+     idle_for = (int) difftime(now, d->last_time);
      /* If they've been connected for 60 seconds without getting a telnet-option
         back, the client probably doesn't understand them */
-     if ((d->conn_flags & CONN_TELNET_QUERY) && idle_for > 60)
+     if ((d->conn_flags & CONN_TELNET_QUERY) && difftime(now, d->connected_at) > 60)
        d->conn_flags &= ~CONN_TELNET_QUERY;
+ #ifndef COMPILE_CONSOLE
+     /* If they've been idle for 60 seconds and are set KEEPALIVE and using
+        a telnet-aware client, send a NOP */
+     if (d->conn_flags & CONN_TELNET && idle_for >= 60
+         && IS(d->player, TYPE_PLAYER, "KEEPALIVE")) {
+       const unsigned char nopmsg[2] = { IAC, NOP };
+       queue_newwrite(d, nopmsg, 2);
+       process_output(d);
+     }
+ #endif
      if(d->connected && GoodObject(d->player) && ((a = atr_get(d->player, "IDLE_TIMEOUT"))!=NULL)) {
 -          memset(tbuf, '\0', BUFFER_LEN);
 -          strncpy(tbuf, atr_value(a), BUFFER_LEN-1);
 -          idle = atoi(tbuf);
 -          if(idle > 0)
 -            goto after_idle_atr_check;
 +            memset(tbuf, '\0', BUFFER_LEN);
 +            strncpy(tbuf, atr_value(a), BUFFER_LEN-1);
 +            idle = atoi(tbuf);
 +            if(idle > 0)
 +              goto after_idle_atr_check;
      } 
      idle = INACTIVITY_LIMIT ? INACTIVITY_LIMIT : INT_MAX;
  after_idle_atr_check:
      if ((d->connected) ? (idle_for > idle ) : (idle_for > unconnected_idle)) {
@@@ -5358,10 -5381,11 +5430,11 @@@ load_reboot_db(void
      }
  
      snprintf(tbuf1, BUFFER_LEN-1, "%ld %ld %d %d", (mudtime - closed->connected_at),
 -       closed->idle_total , closed->unidle_times, closed->cmds);
 +         closed->idle_total , closed->unidle_times, closed->cmds);
      tbuf1[strlen(tbuf1)+1] = '\0';
-     (void) atr_add(closed->player, "LASTACTIVITY", tbuf1, GOD, NOTHING);
+     (void) atr_add(closed->player, "LASTACTIVITY", tbuf1, GOD, 0);
      announce_disconnect(closed->player);
+     mush_free(closed->ttype, "terminal description");
      mush_free(closed, "descriptor");
      closed = nextclosed;
    }
@@@ -5675,15 -5699,15 +5748,15 @@@ COMMAND(cmd_su) 
  
        /* now  chop off last one, and arr2list() */
        if(cnt == 1) { /* clear the attribute */
 -      atr_clr(player, "XYXX_DIVRCD", GOD);
 +        atr_clr(player, "XYXX_DIVRCD", GOD);
        } else {
 -      memset(tbuf, '\0', BUFFER_LEN);
 -      tbp = tbuf;
 -      sep[0] = ' ';
 -      sep[1] = '\0';
 -      arr2list(p_buf, cnt-1, tbuf, &tbp, sep);
 -      /* Add the attribute back */
 +        memset(tbuf, '\0', BUFFER_LEN);
 +        tbp = tbuf;
 +        sep[0] = ' ';
 +        sep[1] = '\0';
 +        arr2list(p_buf, cnt-1, tbuf, &tbp, sep);
 +        /* Add the attribute back */
-         (void) atr_add(player, "XYXX_DIVRCD", tbuf, GOD, NOTHING);
+       (void) atr_add(player, "XYXX_DIVRCD", tbuf, GOD, 0);
        }
      } else {
        notify(player, "Must specify what player you wish to @su into.");
diff --cc src/cmds.c
Simple merge
diff --cc src/command.c
index d0adc1f54305c7418084ed1053d450163464a823,34dff97323cbe549bd898cd7244667b2ab4fab04..fee00aa911b5e938fed53cf2b50c79329699102f
@@@ -249,10 -247,7 +249,7 @@@ COMLIST commands[] = 
     CMD_T_ANY | CMD_T_EQSPLIT | CMD_T_NOGAGGED, NULL},
    {"@REJECTMOTD", NULL, cmd_rejectmotd, CMD_T_ANY, "POWER^SITE"},
    {"@RESTART", "ALL", cmd_restart, CMD_T_ANY | CMD_T_NOGAGGED, NULL},
- #ifdef RPMODE_SYS
-   {"@CRPLOG", "QUIET RESET COMBAT", cmd_rplog, CMD_T_ANY, "POWER^COMBAT"},
- #endif
 - {"@SCAN", "ROOM SELF ZONE GLOBALS", cmd_scan,
 +  {"@SCAN", "ROOM SELF ZONE GLOBALS", cmd_scan,
     CMD_T_ANY | CMD_T_NOGAGGED, NULL},
    {"@SD", "LOGOUT", cmd_su, CMD_T_ANY, NULL},
    {"@SEARCH", NULL, cmd_search,
@@@ -1161,19 -1160,21 +1162,21 @@@ command_parse(dbref player, dbref cause
      }
      if (cmd->type & CMD_T_EQSPLIT) {
        if(rhs_present) {
 -      safe_chr('=', commandraw, &c2);
 -      if (cmd->type & CMD_T_RS_ARGS) {
 -      int rsa_index;
 -      /* This is counterintuitive, but rsa[]
 -       * starts at 1. */
 -      if (rsa[1]) {
 -        safe_str(rsa[1], commandraw, &c2);
 -        for (rsa_index = 2; rsa[rsa_index]; rsa_index++) {
 -          safe_chr(',', commandraw, &c2);
 -          safe_str(rsa[rsa_index], commandraw, &c2);
 +      safe_chr('=', commandraw, &c2);
 +      if (cmd->type & CMD_T_RS_ARGS) {
 +        int rsa_index;
 +        /* This is counterintuitive, but rsa[]
 +         * starts at 1. */
 +        if (rsa[1]) {
 +          safe_str(rsa[1], commandraw, &c2);
 +          for (rsa_index = 2; rsa[rsa_index]; rsa_index++) {
 +            safe_chr(',', commandraw, &c2);
 +            safe_str(rsa[rsa_index], commandraw, &c2);
 +          }
          }
        }
 -      }
+       } else {
+         safe_str(rs, commandraw, &c2);
        }
  #ifdef NEVER
        /* We used to do this, but we're not sure why */
diff --cc src/conf.c
index 28aae90299cf9ef9aa59508f25c316e1a9c3f513,8c9475a362bc877854eba10f098a9a83a7a36707..9ec3bf744cfc6cb0920f306f1aaece66ea58709d
@@@ -1353,12 -1353,12 +1353,12 @@@ config_file_startup(const char *conf, i
        }
      }
      for (cp = (COBRA_CONF *) hash_firstentry(&local_options); cp;
 -       cp = (COBRA_CONF *) hash_nextentry(&local_options)) {
 +         cp = (COBRA_CONF *) hash_nextentry(&local_options)) {
        if (!cp->overridden) {
 -      do_rawlog(LT_ERR,
 -                T
 +        do_rawlog(LT_ERR,
 +                  T
-                   ("CONFIG: local directive '%s' missing from cnf file. using default value."),
+                 ("CONFIG: local directive '%s' missing from cnf file. Using default value."),
 -                cp->name);
 +                  cp->name);
        }
      }
  
@@@ -1580,14 -1580,25 +1580,25 @@@ FUNCTION(fun_config
      safe_str(T("#-1 NO SUCH CONFIG OPTION"), buff, bp);
      return;
    } else {
+     int first = 1;
      for (cp = conftable; cp->name; cp++) {
-       safe_str(cp->name, buff, bp);
+       if (cp->group) {
+       if (first)
+         first = 0;
+       else
 -        safe_chr(' ', buff, bp);
 +      safe_chr(' ', buff, bp);
+       safe_str(cp->name, buff, bp);
+       }
      }
      for (cp = (COBRA_CONF *) hash_firstentry(&local_options); cp;
 -       cp = (COBRA_CONF *) hash_nextentry(&local_options)) {
 +         cp = (COBRA_CONF *) hash_nextentry(&local_options)) {
-       safe_str(cp->name, buff, bp);
+       if (cp->group) {
+       if (first)
+         first = 0;
+       else
 -        safe_chr(' ', buff, bp);
 +      safe_chr(' ', buff, bp);
+       safe_str(cp->name, buff, bp);
+       }
      }
    }
  }
diff --cc src/cque.c
index 69346f651647d811fd9220ba7e5da5579eafe69d,b455e8fd6c3640b6fdcc0ae02be486c52bcbbd24..a64956ee0a003eca13c9e87d6849063b6958b456
@@@ -50,18 -50,18 +50,18 @@@ int  qid_cnt;                   /**< Wh
   * entries (a queue). It is used for all of the queues.
   */
  typedef struct bque {
 -  struct bque *next;                  /**< pointer to next entry on queue */
 -  dbref player;                       /**< player who will do command */
 -  dbref queued;                       /**< object whose QUEUE gets incremented for this command */
 -  dbref cause;                        /**< player causing command (for %N) */
 -  dbref realcause;            /** most of the time same as cause.. except for divisions. */
 -  dbref ooref;                        /**< Used when doing twin checks */
 -  dbref sem;                  /**< semaphore object to block on */
 -  char *semattr;              /**< semaphore attribute to block on */
 +  struct bque *next;                    /**< pointer to next entry on queue */
 +  dbref player;                 /**< player who will do command */
 +  dbref queued;                 /**< object whose QUEUE gets incremented for this command */
 +  dbref cause;                  /**< player causing command (for %N) */
 +  dbref realcause;              /** most of the time same as cause.. except for divisions. */
 +  dbref ooref;                  /**< Used when doing twin checks */
 +  dbref sem;                    /**< semaphore object to block on */
 +  char *semattr;                /**< semaphore attribute to block on */
-   int left;                     /**< seconds left until execution */
+   time_t left;                        /**< seconds left until execution */
 -  char *env[10];              /**< environment, from wild match */
 -  char *rval[NUMQ];           /**< environment, from setq() */
 -  char *comm;                 /**< command to be executed */
 +  char *env[10];                /**< environment, from wild match */
 +  char *rval[NUMQ];             /**< environment, from setq() */
 +  char *comm;                   /**< command to be executed */
  #ifdef _SWMP_
    int sql_env[2];              /**< sql environment 0- Query ID, 1-Auth ID */
  #endif
@@@ -80,8 -80,8 +80,8 @@@ static int add_to_sem(dbref player, in
  static int queue_limit(dbref player);
  void free_qentry(BQUE *point);
  static int pay_queue(dbref player, const char *command);
- int wait_que(dbref player, int wait, char *command,
+ int wait_que(dbref player, int waituntil, char *command,
 -            dbref cause, dbref sem, const char *semattr, int until, char finvoc);
 +              dbref cause, dbref sem, const char *semattr, int until, char finvoc);
  void init_qids();
  int  create_qid();
  int que_next(void);
@@@ -167,10 -167,13 +167,13 @@@ add_to_generic(dbref player, int am, co
    if (a)
      num = parse_integer(atr_value(a));
    num += am;
-   if (num) {
+   /* We set the attribute's value to 0 even if we're going to clear
+    * it later, because clearing it may fail (perhaps someone's also
+    * foolishly using it as a branch in an attribute tree)
+    */
 -  sprintf(buff, "%d", num);
 -  (void) atr_add(player, name, buff, GOD, flags);
 +    sprintf(buff, "%d", num);
 +    (void) atr_add(player, name, buff, GOD, flags);
-   } else {
+   if (!num) {
      (void) atr_clr(player, name, GOD);
    }
    return (num);
@@@ -495,8 -498,8 +498,8 @@@ queue_attribute_useatr(dbref executor, 
   * \param until 1 if we wait until an absolute time.
   */
  int
- wait_que(dbref player, int wait, char *command, dbref cause, dbref sem,
+ wait_que(dbref player, int waittill, char *command, dbref cause, dbref sem,
 -       const char *semattr, int until, char finvoc)
 +         const char *semattr, int until, char finvoc)
  {
    BQUE *tmp;
    int a, qid;
@@@ -698,56 -701,58 +701,58 @@@ do_top(int ncom
        add_to(entry->queued, -1);
        entry->player = 0;
        if (IsPlayer(global_eval_context.cplr) || !Halted(global_eval_context.cplr)) {
 -      for (a = 0; a < 10; a++)
 -        global_eval_context.wenv[a] = entry->env[a];
 -      for (a = 0; a < NUMQ; a++) {
 -        if (entry->rval[a])
 -          strcpy(global_eval_context.renv[a], entry->rval[a]);
 -        else
 -          global_eval_context.renv[a][0] = '\0';
 -      }
 +        for (a = 0; a < 10; a++)
 +          global_eval_context.wenv[a] = entry->env[a];
 +        for (a = 0; a < NUMQ; a++) {
 +          if (entry->rval[a])
 +            strcpy(global_eval_context.renv[a], entry->rval[a]);
 +          else
 +            global_eval_context.renv[a][0] = '\0';
 +        }
          copy_namedregs(&global_eval_context.namedregs, &entry->namedregs);
 -      global_eval_context.process_command_port = 0;
 -      s = entry->comm;
 -      global_eval_context.break_called = 0;
 -      break_count = 100;
 -      *(global_eval_context.break_replace) = '\0';
 -      start_cpu_timer();
 -      while (!cpu_time_limit_hit && *s) {
 -        r = global_eval_context.ccom;
 -        local_ooref = ooref;
 -        ooref = entry->ooref;
 -        if(!entry->fqueued) {
 +        global_eval_context.process_command_port = 0;
 +        s = entry->comm;
 +        global_eval_context.break_called = 0;
 +        break_count = 100;
 +        *(global_eval_context.break_replace) = '\0';
 +        start_cpu_timer();
 +        while (!cpu_time_limit_hit && *s) {
 +          r = global_eval_context.ccom;
 +          local_ooref = ooref;
 +          ooref = entry->ooref;
 +          if(!entry->fqueued) {
-             process_expression(global_eval_context.ccom, &r, &s, global_eval_context.cplr, entry->cause,
+           process_expression(global_eval_context.ccom, &r, &s, 
+               global_eval_context.cplr, entry->cause, 
 -              entry->realcause, PE_NOTHING, PT_SEMI, NULL);
 -          *r = '\0';
 -          if (*s == ';')
 -            s++;
 -           strcpy(tbuf, global_eval_context.ccom);
 -           process_command(global_eval_context.cplr, tbuf, entry->cause, entry->realcause, 0);
 -           if(global_eval_context.break_called) {
 -             global_eval_context.break_called = 0;
 -             s = global_eval_context.break_replace;
 -             if(!*global_eval_context.break_replace) {
 -               ooref = local_ooref;
 -               break;
 -             }
 -             break_count--;
 -             if(!break_count) {
 -               notify(global_eval_context.cplr, T("@break recursion exceeded."));
 -               ooref = local_ooref;
 -               break;
 -             }
 -           }
 -        } else {
 +                             entry->realcause, PE_NOTHING, PT_SEMI, NULL);
 +            *r = '\0';
 +            if (*s == ';')
 +              s++;
 +             strcpy(tbuf, global_eval_context.ccom);
 +             process_command(global_eval_context.cplr, tbuf, entry->cause, entry->realcause, 0);
 +             if(global_eval_context.break_called) {
 +               global_eval_context.break_called = 0;
 +               s = global_eval_context.break_replace;
 +               if(!*global_eval_context.break_replace) {
 +                 ooref = local_ooref;
 +                 break;
 +               }
 +               break_count--;
 +               if(!break_count) {
 +                 notify(global_eval_context.cplr, T("@break recursion exceeded."));
 +                 ooref = local_ooref;
 +                 break;
 +               }
 +             }
 +          } else {
-                   process_expression(global_eval_context.ccom, &r, &s, global_eval_context.cplr, entry->cause, entry->realcause, PE_DEFAULT, 
+                 process_expression(global_eval_context.ccom, &r, &s, 
+                     global_eval_context.cplr, entry->cause, entry->realcause, PE_DEFAULT, 
 -                    PT_DEFAULT, (PE_Info *) NULL);
 -                *r = '\0';
 -                notify(global_eval_context.cplr, global_eval_context.ccom);
 -        }
 -        ooref = local_ooref;
 -      }
 -      reset_cpu_timer();
 +                                  PT_DEFAULT, (PE_Info *) NULL);
 +                  *r = '\0';
 +                  notify(global_eval_context.cplr, global_eval_context.ccom);
 +          }
 +          ooref = local_ooref;
 +        }
 +        reset_cpu_timer();
        }
      }
      free_qentry(entry);
@@@ -1085,29 -1090,31 +1090,31 @@@ show_queue(dbref player, dbref victim, 
      if (!GoodObject(tmp->player))
        (*del)++;
      else if (q_all || (Owner(tmp->player) == victim)) {
-       (*self)++;
-       if (!q_quiet && (CanSeeQ(player, victim)
+       if ((CanSeeQ(player, victim)
 -                     || Owns(tmp->player, player))) {
 +                       || Owns(tmp->player, player))) {
+       (*self)++;
+       if(q_quiet)
+         continue;
 -      switch (q_type) {
 -      case 1:         /* wait queue */
 -        notify_format(player, "[QID: %d%s/%ld]%s:%s", tmp->qid, qid_table[tmp->qid] == QID_FREEZE ? "(F)" : "",
 -                        tmp->left - mudtime, unparse_object(player, tmp->player), tmp->comm);
 -        break;
 -      case 2:         /* semaphore queue */
 -        if (tmp->left != 0) {
 -          notify_format(player, "[QID: %d%s/#%d/%s/%ld]%s:%s", tmp->qid, qid_table[tmp->qid] == QID_FREEZE ? "(F)" : "",
 -                          tmp->sem, tmp->semattr, tmp->left - mudtime,
 -                        unparse_object(player, tmp->player), tmp->comm);
 -        } else {
 -          notify_format(player, "[QID: %d%s/#%d/%s]%s:%s", tmp->qid, qid_table[tmp->qid] == QID_FREEZE ? "(F)" : "",
 -                          tmp->sem, tmp->semattr, unparse_object(player, tmp->player),
 -                        tmp->comm);
 -        }
 -        break;
 -      default:                /* player or object queue */
 -        notify_format(player, "[QID: %d%s] %s:%s", tmp->qid, qid_table[tmp->qid] == QID_FREEZE ? "(F)" : "", 
 -                        unparse_object(player, tmp->player), tmp->comm);
 -      }
 +        switch (q_type) {
 +        case 1:         /* wait queue */
 +          notify_format(player, "[QID: %d%s/%ld]%s:%s", tmp->qid, qid_table[tmp->qid] == QID_FREEZE ? "(F)" : "",
 +                          tmp->left - mudtime, unparse_object(player, tmp->player), tmp->comm);
 +          break;
 +        case 2:         /* semaphore queue */
 +          if (tmp->left != 0) {
 +            notify_format(player, "[QID: %d%s/#%d/%s/%ld]%s:%s", tmp->qid, qid_table[tmp->qid] == QID_FREEZE ? "(F)" : "",
 +                            tmp->sem, tmp->semattr, tmp->left - mudtime,
 +                          unparse_object(player, tmp->player), tmp->comm);
 +          } else {
 +            notify_format(player, "[QID: %d%s/#%d/%s]%s:%s", tmp->qid, qid_table[tmp->qid] == QID_FREEZE ? "(F)" : "",
 +                            tmp->sem, tmp->semattr, unparse_object(player, tmp->player),
 +                          tmp->comm);
 +          }
 +          break;
 +        default:                /* player or object queue */
 +          notify_format(player, "[QID: %d%s] %s:%s", tmp->qid, qid_table[tmp->qid] == QID_FREEZE ? "(F)" : "", 
 +                          unparse_object(player, tmp->player), tmp->comm);
 +        }
        }
      }
    }
diff --cc src/db.c
index 6289a68ae89981aef222d3102e181b3405ee4083,2fa080f884485eaacd64b7022c4eb66b2725027a..23d5eb49199c9d055c0fd19c67960022d09d5cbd
+++ b/src/db.c
@@@ -1281,14 -1294,13 +1298,13 @@@ get_list(FILE * f, dbref i
        }
        *q++ = '\0';
        flags = atoi(q);
-       /* Remove obsolete AF_NUKED flag and AF_STATIC, just in case */
+       /* Remove obsolete AF_NUKED flag just in case */
        flags &= ~AF_NUKED;
-       flags &= ~AF_STATIC;
        if (!(indb_flags & DBF_AF_VISUAL)) {
 -      /* Remove AF_ODARK flag. If it wasn't there, set AF_VISUAL */
 -      if (!(flags & AF_ODARK))
 -        flags |= AF_VISUAL;
 -      flags &= ~AF_ODARK;
 +        /* Remove AF_ODARK flag. If it wasn't there, set AF_VISUAL */
 +        if (!(flags & AF_ODARK))
 +          flags |= AF_VISUAL;
 +        flags &= ~AF_ODARK;
        }
        /* Read in the deref count for the attribute, or set it to 0 if not
           present. */
@@@ -2154,12 -2181,12 +2188,12 @@@ create_minimal_db(void
  
    int desc_flags = AF_VISUAL | AF_NOPROG | AF_PREFIXMATCH;
  
 -  start_room = new_object();  /* #0 */
 -  god = new_object();         /* #1 */
 -  master_room = new_object(); /* #2 */
 +  start_room = new_object();    /* #0 */
 +  god = new_object();           /* #1 */
 +  master_room = new_object();   /* #2 */
    master_division = new_object(); /* #3 */
  
-   init_objdata_htab(DB_INITIAL_SIZE);
+   init_objdata_htab(DB_INITIAL_SIZE, NULL);
  
    set_name(start_room, "Room Zero");
    Type(start_room) = TYPE_ROOM;
diff --cc src/destroy.c
index 888db1cd0601e58cccf85eae8973ae57b6fd115a,bafc8caf1eff4d686d4f35b4bdea33f49a67787d..014a895c86ddaffbaef9557265086e9562f65a2c
@@@ -900,12 -891,7 +900,7 @@@ static voi
  clear_room(dbref thing)
  {
    dbref first, rest;
- #ifdef RPMODE_SYS
-   /* Clear RPLOGging crapp */
-   if(has_flag_by_name(thing, "ICFUNCS", TYPE_THING))
-     rplog_shutdown_room(thing);
- #endif /* RPMODE_SYS */
 - /* give player money back */
 +  /* give player money back */
    giveto(Owner(thing), ROOM_COST);
    empty_contents(thing);
    /* Remove exits */
diff --cc src/division.c
Simple merge
diff --cc src/extchat.c
index 5f43962a3f3f39c218afe70ea43a1e2fe915466e,5bab81653ae551a157187f335d029eb3cd295feb..af55dd2f0918e1c21e525fd97dc670137bee8ccc
@@@ -3673,9 -3675,11 +3675,11 @@@ do_chan_buffer(dbref player, const cha
    }
  }
  
+ /* msg is a printf-style format that has exactly and only 2 %s specifiers
+    in it. */
  static void
  format_channel_broadcast(CHAN *chan, CHANUSER *u, dbref victim, int flags,
 -                       const char *msg, const char *extra)
 +                         const char *msg, const char *extra)
  {
    const char *title = NULL;
    if (extra && *extra)
diff --cc src/extmail.c
Simple merge
diff --cc src/filecopy.c
index c05d52b086ce048537a2ce9a82bae8d7678a1849,dfcc5ad6582816db3f7edf22ead3ce01fddbc236..ec65075f09eee90c1d6b648a3c2884ca6d4b6401
@@@ -197,13 -197,13 +197,13 @@@ Win32MUSH_setup(void
  #ifndef _DEBUG
    char FileName[256];
    if (GetModuleFileName(NULL, FileName, 256) != 0) {
-     if (!strcasecmp(rindex(FileName, '\\') + 1, "cobramush.exe")) {
+     if (!strcasecmp(strrchr(FileName, '\\') + 1, "cobramush.exe")) {
        if (CopyFile("cobramush.exe", "cobramush_run.exe", FALSE)) {
 -      do_rawlog(LT_ERR, "Successfully copied executable, starting copy.");
 +        do_rawlog(LT_ERR, "Successfully copied executable, starting copy.");
  #ifdef WIN32SERVICES
 -      execl("cobramush_run.exe", "cobramush_run.exe", "/run", NULL);
 +        execl("cobramush_run.exe", "cobramush_run.exe", "/run", NULL);
  #else
 -      execl("cobramush_run.exe", "cobramush_run.exe", confname, NULL);
 +        execl("cobramush_run.exe", "cobramush_run.exe", confname, NULL);
  #endif
        }
      }
diff --cc src/flags.c
index 60fe5956e2d36275c5615ea18bec85c8379f939a,e0e98ffd1f754020213fc14397664c6cde1ab803..e636823e5fe11c5f1f8f1822b1ed711e9c431fc0
@@@ -579,9 -606,25 +606,25 @@@ flag_read_all(FILE * in, const char *ns
      if ((f = flag_read(in))) 
       flag_add(n, f->name, f);
    }
+   if (found != count) 
+     do_rawlog(LT_ERR,
+             T("WARNING: Actual number of flags (%d) different than expected count (%d)."),
+             found, count);
+  
   /* Assumes we'll always have at least one alias */
 -  db_read_this_labeled_number(in, "flagaliascount", &count);        
 +  db_read_this_labeled_number(in, "flagaliascount", &count);
-   for (; count > 0; count--) {
+   for (found = 0 ;;) {
+     int c;
+     
+     c = fgetc(in);
+     ungetc(c, in);
+     if (c != ' ')
+       break;
+     found++;
      if ((f = flag_alias_read(in, alias, n)))
        flag_add(n, alias, f);
    }
@@@ -752,11 -801,12 +801,12 @@@ flag_add_additional(void
    add_flag("EMPIRE", 'E', TYPE_DIVISION, F_PRIVILEGE, F_PRIVILEGE);
    add_flag("INHERIT", 'I', TYPE_THING | TYPE_EXIT | TYPE_ROOM, F_PRIVILEGE, F_PRIVILEGE);
    add_flag("INHERITABLE", 'I', TYPE_PLAYER, F_PRIVILEGE | F_SELF,
 -         F_PRIVILEGE | F_SELF);
 +           F_PRIVILEGE | F_SELF);
    add_flag("ZCLONE_OK", '\0', TYPE_THING, F_PRIVILEGE, F_PRIVILEGE);
    add_flag("WEIRDSITE", '\0', TYPE_PLAYER, F_GOD | F_DARK, F_GOD | F_DARK);
+   add_flag("KEEPALIVE", 'k', TYPE_PLAYER, F_ANY, F_ANY);
    add_flag("MISTRUST", 'm', TYPE_THING | TYPE_EXIT | TYPE_ROOM, F_PRIVILEGE,
 -         F_PRIVILEGE);
 +           F_PRIVILEGE);
    add_flag("ORPHAN", 'i', NOTYPE, F_ANY, F_ANY);
    add_flag("TRACK_MONEY", '\0', TYPE_PLAYER, F_ANY, F_ANY);
    add_flag("LOUD", '\0', NOTYPE, F_PRIVILEGE, F_ANY);
@@@ -1286,8 -1338,9 +1336,9 @@@ unparse_flags(dbref thing, dbref player
    }
    for (i = 0; i < n->flagbits; i++) {
      if ((f = n->flags[i])) {
-       if (has_flag(thing, f) && Can_See_Flag(player, thing, f))
+       if (has_flag(thing, f) && Can_See_Flag(player, thing, f) 
+         && f->letter)
 -      *p++ = f->letter;
 +        *p++ = f->letter;
      }
    }
    *p = '\0';
@@@ -1418,69 -1471,69 +1469,69 @@@ set_flag(dbref player, dbref thing, con
    }
    if(is_flag(f, "RPMODE")) {
         if(atr_get(thing, "RPLOCK") != NULL) {
 -       notify_format(player, "That player is currently locked %s RPMode.", RPMODE(thing) ? "into" : "out of");
 -       return;
 +         notify_format(player, "That player is currently locked %s RPMode.", RPMODE(thing) ? "into" : "out of");
 +         return;
         }
 -        if(negate) {
 -                if(!RPMODE(thing)) {
 -                        notify(player, "That player isn't currently in RPMODE.");
 -                        return;
 -                }
 -                icloc = GoodObject((absroom = absolute_room(thing))) ? absroom : thing;
 -                if(GoodObject(icloc) && has_flag_by_name(icloc, "ICFUNCS" , NOTYPE) 
 -                        && !Going(icloc)) {
 +          if(negate) {
 +                  if(!RPMODE(thing)) {
 +                          notify(player, "That player isn't currently in RPMODE.");
 +                          return;
 +                  }
 +                  icloc = GoodObject((absroom = absolute_room(thing))) ? absroom : thing;
 +                  if(GoodObject(icloc) && has_flag_by_name(icloc, "ICFUNCS" , NOTYPE) 
 +                          && !Going(icloc)) {
-                                   (void) atr_add(thing, "INF_RPLOC", unparse_dbref(Location(thing)), GOD, NOTHING); 
+                                 (void) atr_add(thing, "INF_RPLOC", unparse_dbref(Location(thing)), GOD, 0); 
 -                                icloc = Home(thing);
 -                        } else {
 -                                notify(player, "That player is not an IC Location, therefore can't go OOC.");
 -                                return;
 -                        }
 -        } else {
 -                if(RPMODE(thing)) {
 -                        notify(player, "That player is already in RPMODE.");
 -                        return;
 -                }
 -                if(InProg(thing)) {
 -                  notify(player, "Permission denied. Can not go RPMODE while in a @PROGRAM.");
 -                  return;
 -                }
 -                /* First make sure there truerace is valid */
 -                icloc_ptr = atr_get(thing, "TRUERACE");
 -                if(icloc_ptr) 
 -                  strncpy(icloc_buf, atr_value(icloc_ptr), BUFFER_LEN-1);
 -                if(!*icloc_buf) {
 -                        if(player != thing)
 -                                notify(player, "That player does not have a valid TRUERACE set.");
 -                        notify(thing, "You do not have a valid TRUERACE set.  Contact an administrator.");
 -                        return;
 -                } else if(parse_dbref(icloc_buf) == NOTHING) {
 -                        if(player != thing)
 -                                notify(player, "That player has an invalid TRUERACE.");
 -                        notify(thing, "You have an invalid TRUERACE.  Contact an administrator.");
 -                        return;
 -                }
 -                icloc_ptr = atr_get(thing, "INF_RPLOC");
 -                memset(icloc_buf, '\0', BUFFER_LEN);
 -                if(icloc_ptr)
 -                        strncpy(icloc_buf, atr_value(icloc_ptr), BUFFER_LEN-1);
 -                if(!*icloc_buf) {
 -                        if(player != thing)
 -                          notify(player, "That player has an invalid RP location set."); 
 -                        notify(thing, "You have an invalid RP location set.  Contact an administrator.");
 -                        return;
 -                }
 -                
 -                icloc = parse_dbref(icloc_buf);
 -                icloc = GoodObject((absroom = absolute_room(icloc))) ? absroom : icloc;
 -
 -                if(!GoodObject(icloc) ||  !has_flag_by_name(icloc, "ICFUNCS", NOTYPE) || Going(icloc)) {
 -                        if(player != thing)
 -                          notify(player, "That player has an invalid RP location set.");
 -                        notify(thing, "You have an invalid RP location set.  Contact an administrator.");
 -                        return;
 -                }
 -                /* Ok.. everythings good, move 'em to the IC world */
 -        }
 +                                  icloc = Home(thing);
 +                          } else {
 +                                  notify(player, "That player is not an IC Location, therefore can't go OOC.");
 +                                  return;
 +                          }
 +          } else {
 +                  if(RPMODE(thing)) {
 +                          notify(player, "That player is already in RPMODE.");
 +                          return;
 +                  }
 +                  if(InProg(thing)) {
 +                    notify(player, "Permission denied. Can not go RPMODE while in a @PROGRAM.");
 +                    return;
 +                  }
 +                  /* First make sure there truerace is valid */
 +                  icloc_ptr = atr_get(thing, "TRUERACE");
 +                  if(icloc_ptr) 
 +                    strncpy(icloc_buf, atr_value(icloc_ptr), BUFFER_LEN-1);
 +                  if(!*icloc_buf) {
 +                          if(player != thing)
 +                                  notify(player, "That player does not have a valid TRUERACE set.");
 +                          notify(thing, "You do not have a valid TRUERACE set.  Contact an administrator.");
 +                          return;
 +                  } else if(parse_dbref(icloc_buf) == NOTHING) {
 +                          if(player != thing)
 +                                  notify(player, "That player has an invalid TRUERACE.");
 +                          notify(thing, "You have an invalid TRUERACE.  Contact an administrator.");
 +                          return;
 +                  }
 +                  icloc_ptr = atr_get(thing, "INF_RPLOC");
 +                  memset(icloc_buf, '\0', BUFFER_LEN);
 +                  if(icloc_ptr)
 +                          strncpy(icloc_buf, atr_value(icloc_ptr), BUFFER_LEN-1);
 +                  if(!*icloc_buf) {
 +                          if(player != thing)
 +                            notify(player, "That player has an invalid RP location set."); 
 +                          notify(thing, "You have an invalid RP location set.  Contact an administrator.");
 +                          return;
 +                  }
 +                  
 +                  icloc = parse_dbref(icloc_buf);
 +                  icloc = GoodObject((absroom = absolute_room(icloc))) ? absroom : icloc;
 +
 +                  if(!GoodObject(icloc) ||  !has_flag_by_name(icloc, "ICFUNCS", NOTYPE) || Going(icloc)) {
 +                          if(player != thing)
 +                            notify(player, "That player has an invalid RP location set.");
 +                          notify(thing, "You have an invalid RP location set.  Contact an administrator.");
 +                          return;
 +                  }
 +                  /* Ok.. everythings good, move 'em to the IC world */
 +          }
    }
  #endif /* RPMODE_SYS */
  
@@@ -1744,29 -1797,37 +1795,37 @@@ flaglist_check(const char *ns, dbref pl
         * Fail the check. */
        return (type == 1) ? 0 : ret;
      /* Find the flag. */
-     if ((fp = letter_to_flagptr(n, *s, Typeof(it))) == NULL) {
+     fp = letter_to_flagptr(n, *s, Typeof(it));
+     if (!fp) {
+       if (n->tab == &ptab_flag) {
 -        /* Maybe *s is a type specifier (P, T, E, R). These aren't really
 -         * flags, but we grandfather them in to preserve old code
 -         */
 -        if ((*s == 'T') || (*s == 'R') || (*s == 'E') || (*s == 'P')) {
 -          temp = (*s == 'T') ? (Typeof(it) == TYPE_THING) :
 -            ((*s == 'R') ? (Typeof(it) == TYPE_ROOM) :
 -             ((*s == 'E') ? (Typeof(it) == TYPE_EXIT) :
 -              (Typeof(it) == TYPE_PLAYER)));
 -          if ((type == 1) && ((negate && temp) || (!negate && !temp)))
 -            return 0;
 -          else if ((type == 0) && ((!negate && temp) || (negate && !temp)))
 -            ret |= 1;
 -        } else {
 -          /* Either we got a '!' that wasn't followed by a letter, or
 -           * we couldn't find that flag. For AND, since we've failed
 -           * a check, we can return false. Otherwise we just go on.
 -           */
 -          if (type == 1)
 -            return 0;
 -          else
 -            continue;
 -        }
 +      /* Maybe *s is a type specifier (P, T, E, R). These aren't really
 +       * flags, but we grandfather them in to preserve old code
 +       */
 +      if ((*s == 'T') || (*s == 'R') || (*s == 'E') || (*s == 'P')) {
 +        temp = (*s == 'T') ? (Typeof(it) == TYPE_THING) :
 +          ((*s == 'R') ? (Typeof(it) == TYPE_ROOM) :
 +           ((*s == 'E') ? (Typeof(it) == TYPE_EXIT) :
 +            (Typeof(it) == TYPE_PLAYER)));
 +        if ((type == 1) && ((negate && temp) || (!negate && !temp)))
 +          return 0;
 +        else if ((type == 0) && ((!negate && temp) || (negate && !temp)))
 +          ret |= 1;
        } else {
 +        /* Either we got a '!' that wasn't followed by a letter, or
 +         * we couldn't find that flag. For AND, since we've failed
 +         * a check, we can return false. Otherwise we just go on.
 +         */
 +        if (type == 1)
 +          return 0;
 +        else
 +          continue;
 +      }
++    } else {
+         if (type == 1)
+           return 0;
+         else
+           continue;
+       }
      } else {
        /* does the object have this flag? */
        temp = (has_flag(it, fp) && Can_See_Flag(player, it, fp));
@@@ -2321,9 -2380,14 +2378,14 @@@ alias_flag_generic(const char *ns, cons
    }
  
    if (ptab_find_exact(n->tab, strupper(alias))) {
 -    return 0;                   /* a flag called 'alias' already exists */
 +    return 0;                 /* a flag called 'alias' already exists */
    }
  
+   if (FLAG_REF(f->perms) == 0xFFU)
+     return 0;                   /* Too many copies already */
+   f->perms = INCR_FLAG_REF(f->perms);
    ptab_start_inserts(n->tab);
    ptab_insert(n->tab, strupper(alias), f);
    ptab_end_inserts(n->tab);
diff --cc src/function.c
Simple merge
diff --cc src/fundb.c
Simple merge
diff --cc src/funlist.c
Simple merge
diff --cc src/funmisc.c
index 6198dfebc8719aa151d9ab3b084616fdb57284c3,d17a7c986b836e9058e3f7161adde02c0edc6fde..98f254350bd08a6df06ee4f25da455909f328bd7
@@@ -341,11 -343,15 +343,15 @@@ FUNCTION(fun_switch
  
    if (!(nargs & 1) && !found) {
      /* Default case */
 -      tbuf1 = replace_string("#$", mstr, args[nargs - 1]);
 -      sp = tbuf1;
+     if (!exact) {
 +    tbuf1 = replace_string("#$", mstr, args[nargs - 1]);
 +    sp = tbuf1;
+     } else
+       sp = args[nargs - 1];
      process_expression(buff, bp, &sp, executor, caller, enactor,
                         PE_DEFAULT, PT_DEFAULT, pe_info);
 -      mush_free((Malloc_t) tbuf1, "replace_string.buff");
+     if (!exact)
 +    mush_free((Malloc_t) tbuf1, "replace_string.buff");
    }
  }
  
diff --cc src/funstr.c
index 354a40cc92ab94f04ddb131d359aa43f419d9be0,539fc9641f8c16755fc650c2df4813078559ccbb..3b11cf03a7ac25fdb1480005495b0eb3c91d2887
@@@ -686,54 -676,83 +676,83 @@@ FUNCTION(fun_tr
      charmap[i] = (char) i;
    }
  
+ #define goodchr(x) (isprint(x) || (x == '\n'))
+   /* Convert ranges in input string, and check that
+    * we don't receive a nonprinting char such as
+    * beep() */
    ip = instr;
-   op = outstr;
-   for (i = 0; i < len; i++) {
-     safe_chr(rawstr[i], instr, &ip);
-     /* Handle a range of characters */
-     if (i != len - 1 && rawstr[i + 1] == '-' && i != len - 2) {
-       int dir, sentinel, cur;
-       if (rawstr[i] < rawstr[i + 2])
-         dir = 1;
-       else
-         dir = -1;
-       sentinel = rawstr[i + 2] + dir;
-       cur = rawstr[i] + dir;
-       while (cur != sentinel) {
-         safe_chr((char) cur, instr, &ip);
-         cur += dir;
+   c = remove_markup(args[1], NULL);
+   while (*c) {
+     cur = (unsigned char) *c;
+     if (!goodchr(cur)) {
+       safe_str(T("#-1 TR CANNOT ACCEPT NONPRINTING CHARS"), buff, bp);
+       return;
 -    }
 +      }
-       i += 2;
+     /* Tack it onto the string */
+     /* Do we have a range? */
+     if (*(c + 1) && *(c + 1) == '-' && *(c + 2)) {
+       dest = (unsigned char) *(c + 2);
+       if (!goodchr(dest)) {
+         safe_str(T("#-1 TR CANNOT ACCEPT NONPRINTING CHARS"), buff, bp);
+         return;
 -      }
 +    }
+       if (dest > cur) {
+         for (; cur <= dest; cur++) {
+           if (goodchr(cur))
+             safe_chr(cur, instr, &ip);
 -        }
 +  }
+       } else {
+         for (; cur >= dest; cur--) {
+           if (goodchr(cur))
+             safe_chr(cur, instr, &ip);
+         }
+       }
+       c += 3;
+     } else {
+       safe_chr(cur, instr, &ip);
+       c++;
+     }
+   }
+   *ip = '\0';
  
-   c = remove_markup(args[2], &len);
-   memcpy(rawstr, c, len);
-   for (i = 0; i < len; i++) {
-     safe_chr(rawstr[i], outstr, &op);
-     /* Handle a range of characters */
-     if (i != len - 1 && rawstr[i + 1] == '-' && i != len - 2) {
-       int dir, sentinel, cur;
-       if (rawstr[i] < rawstr[i + 2])
-         dir = 1;
-       else
-         dir = -1;
-       sentinel = rawstr[i + 2] + dir;
-       cur = rawstr[i] + dir;
-       while (cur != sentinel) {
-         safe_chr((char) cur, outstr, &op);
-         cur += dir;
+   /* Convert ranges in output string, and check that
+    * we don't receive a nonprinting char such as
+    * beep() */
+   op = outstr;
+   c = remove_markup(args[2], NULL);
+   while (*c) {
+     cur = (unsigned char) *c;
+     if (!goodchr(cur)) {
+       safe_str(T("#-1 TR CANNOT ACCEPT NONPRINTING CHARS"), buff, bp);
+       return;
+     }
+     /* Tack it onto the string */
+     /* Do we have a range? */
+     if (*(c + 1) && *(c + 1) == '-' && *(c + 2)) {
+       dest = (unsigned char) *(c + 2);
+       if (!goodchr(dest)) {
+         safe_str(T("#-1 TR CANNOT ACCEPT NONPRINTING CHARS"), buff, bp);
+         return;
        }
-       i += 2;
+       if (dest > cur) {
+         for (; cur <= dest; cur++) {
+           if (goodchr(cur))
+             safe_chr(cur, outstr, &op);
 -        }
 +    }
+       } else {
+         for (; cur >= dest; cur--) {
+           if (goodchr(cur))
+             safe_chr(cur, outstr, &op);
+         }
+       }
+       c += 3;
+     } else {
+       safe_chr(cur, outstr, &op);
+       c++;
 -    }
++  }
    }
+   *op = '\0';
+ #undef goodchr
  
    if ((ip - instr) != (op - outstr)) {
      safe_str(T("#-1 STRING LENGTHS MUST BE EQUAL"), buff, bp);
diff --cc src/funtime.c
Simple merge
diff --cc src/game.c
index dc4cb1cd2ff5777acf81ef49ae67032f823ba206,3b6ea533b66c6761a45129e45a28024b904d79cb..c17070fc8c0b7feacb6218381bdc6724828ba855
@@@ -572,8 -566,8 +574,8 @@@ dump_database(void
    epoch++;
  
    do_rawlog(LT_ERR, "DUMPING: %s.#%d#", globals.dumpfile, epoch);
-   dump_database_internal();
+   if (!dump_database_internal())
 -    do_rawlog(LT_ERR, "DUMPING: %s.#%d# (done)", globals.dumpfile, epoch);
 +  do_rawlog(LT_ERR, "DUMPING: %s.#%d# (done)", globals.dumpfile, epoch);
  }
  
  /** Dump a database, possibly by forking the process.
@@@ -2274,12 -2255,15 +2276,15 @@@ do_uptime(dbref player, int mortal
    }
  
    notify_format(player,
 -                T
 -                ("PennMUSH Uptime: %ld days %ld hours %ld minutes %ld seconds"),
 +              T
-               ("PennMUSH Uptime: %ld days %ld hours %ld minutes %ld seconds"),
-               (mudtime - globals.first_start_time) / 86400,
-               ((mudtime - globals.first_start_time) % 86400) / 3600,
-               (((mudtime - globals.first_start_time) % 86400) % 3600) / 60,
-               (((mudtime - globals.first_start_time) % 86400) % 3600) % 60);
++              ("CobraMUSH Uptime: %ld days %ld hours %ld minutes %ld seconds"),
+                 ((long) difftime(mudtime, globals.first_start_time)) / 86400,
+                 ((long) difftime(mudtime, globals.first_start_time) % 86400) /
+                 3600,
+                 (((long) difftime(mudtime, globals.first_start_time) % 86400) %
+                  3600) / 60,
+                 (((long) difftime(mudtime, globals.first_start_time) % 86400) %
+                  3600) % 60);
  
    /* Mortals, go no further! */
    if (!Site(player) || mortal)
diff --cc src/lock.c
index 90df30a4c2e2668d9c9174e4705a79b7fc904767,16e56b212aa845dd258675be2d9057028be4abb4..d32c126dc9c094d27e2ea6bdc429f782dc35f54a
@@@ -800,9 -802,11 +802,11 @@@ in
  eval_lock(dbref player, dbref thing, lock_type ltype)
  {
    boolexp b = getlock(thing, ltype);
-   log_activity(LA_LOCK, thing, unparse_boolexp(player, b, UB_DBREF));
 - if(Pass_Lock(player, thing) && IS_passlock_type(ltype))
 +  if(Pass_Lock(player, thing) && IS_passlock_type(ltype))
      return 1;
+   /* Prevent overwriting a static buffer in unparse_boolexp() */
+   if (!unparsing_boolexp)
+     log_activity(LA_LOCK, thing, unparse_boolexp(player, b, UB_DBREF));
    return eval_boolexp(player, getlock(thing, ltype), thing, NULL);
  }
  
diff --cc src/look.c
index 9ccf057d47ab8fac66a98f6d3fd9daf33546c75a,5d96b67b469ac96f335cfc2f5091607d16e6391b..56eebd81a43dfc91a7ecaf18d64b3274ff73c277
@@@ -45,9 -47,11 +47,11 @@@ static int look_helpe
  static int look_helper_veiled
    (dbref player, dbref thing, dbref target, char const *pattern, ATTR *atr, void *args);
  void decompile_atrs(dbref player, dbref thing, const char *name,
 -                  const char *pattern, const char *prefix, int skipdef);
 +                    const char *pattern, const char *prefix, int skipdef);
  void decompile_locks(dbref player, dbref thing, const char *name, int skipdef);
  
+ static void insert_spaces(int count, int dospace, char *buff, char **bp);
  extern PRIV attr_privs_view[];
  
  static void
@@@ -1463,152 -1499,154 +1499,154 @@@ decompose_str(char *what
        safe_str("%t", value, &s);
        break;
      case ESC_CHAR:
+       insert_spaces(spaces, dospace, value, &s);
+       spaces = 0;
        ptr++;
        if (!*ptr) {
 -      ptr--;
 -      break;
 +        ptr--;
 +        break;
        }
        /* Check if this is any sort of useful code. */
        if (*ptr == '[' && *(ptr + 1) && *(ptr + 2)) {
 -      codestart = ptr;        /* Save the address of the escape code. */
 -      ptr++;
 -      digits = 0;             /* Digit count is zero. */
 -      /* The following code works in this way:
 -       * 1) If a character is a ;, we are allowed to count 2 more digits
 -       * 2) If the digits count is 3, break out of the "ansi" code.
 -       * 3) If the character is not a number or ;, break out.
 -       * 4) If an 'm' is encountered, the for-loop exits.
 -       * The only non-breaking exit occurs when the code ends with "m".
 -       * Otherwise, we break out with the ptr pointing to the end of
 -       * the invalid code, causing decompose() to ignore it entirely.
 -       */
 -      for (; *ptr && (*ptr != 'm'); ptr++) {
 -        if (*ptr == ';') {
 -          if (digits == 0) {  /* No double-;s are allowed. */
 -            digits = 3;
 -            break;
 -          }
 -          digits = 0;
 -        } else if (digits >= 2) {
 -          digits = 3;         /* If we encounter a 3-number code, break out. */
 -          break;
 +        codestart = ptr;        /* Save the address of the escape code. */
 +        ptr++;
 +        digits = 0;             /* Digit count is zero. */
 +        /* The following code works in this way:
 +         * 1) If a character is a ;, we are allowed to count 2 more digits
 +         * 2) If the digits count is 3, break out of the "ansi" code.
 +         * 3) If the character is not a number or ;, break out.
 +         * 4) If an 'm' is encountered, the for-loop exits.
 +         * The only non-breaking exit occurs when the code ends with "m".
 +         * Otherwise, we break out with the ptr pointing to the end of
 +         * the invalid code, causing decompose() to ignore it entirely.
 +         */
 +        for (; *ptr && (*ptr != 'm'); ptr++) {
 +          if (*ptr == ';') {
 +            if (digits == 0) {  /* No double-;s are allowed. */
 +              digits = 3;
 +              break;
 +            }
 +            digits = 0;
 +          } else if (digits >= 2) {
 +            digits = 3;         /* If we encounter a 3-number code, break out. */
 +            break;
-           } else if (isdigit(*ptr)) {
+         } else if (isdigit((unsigned char) *ptr)) {
 -          digits++;           /* Count the numbers we encounter. */
 -        } else {
 -          digits = 3;
 -          break;
 -        }
 -      }
 -
 -      /* 3 is the break-code. 0 means there's no ANSI at all! */
 -      if (!*ptr || digits == 3 || digits == 0) {
 -        break;
 -      }
 -
 -      /* It IS an ansi code! It ends in "m" anyway.
 -       * Set ptr to point to the first digit in the code. We are
 -       * promised at this point that ptr+1 is not NUL.
 -       */
 -      ptr = codestart + 1;
 -
 -      /* Check if the first part of the code is two-digit (color) */
 -      if (*(ptr + 1) >= '0' && *(ptr + 1) <= '7') {
 -        if (flag_depth < ansi_depth) {
 -          safe_str(")]", value, &s);
 -          ansi_depth--;
 -        }
 -      } else {                /* ansi "flag", inverse, flash, underline, hilight */
 -        flag_depth = ansi_depth + 1;
 -      }
 -      /* Check to see if this is an 'ansi-reset' code. */
 -      if (*ptr == '0' && *(ptr + 1) == 'm') {
 -        for (; ansi_depth > 0; ansi_depth--) {
 -          safe_str(")]", value, &s);
 -        }
 -        flag_depth = 0;
 -        ptr++;
 -        break;
 -      }
 -
 -      ansi_depth++;
 -      safe_str("[ansi(", value, &s);
 -      dospace = 1;
 -
 -      /* code for decompiling ansi */
 +            digits++;           /* Count the numbers we encounter. */
 +          } else {
 +            digits = 3;
 +            break;
 +          }
 +        }
 +
 +        /* 3 is the break-code. 0 means there's no ANSI at all! */
 +        if (!*ptr || digits == 3 || digits == 0) {
 +          break;
 +        }
 +
 +        /* It IS an ansi code! It ends in "m" anyway.
 +         * Set ptr to point to the first digit in the code. We are
 +         * promised at this point that ptr+1 is not NUL.
 +         */
 +        ptr = codestart + 1;
 +
 +        /* Check if the first part of the code is two-digit (color) */
 +        if (*(ptr + 1) >= '0' && *(ptr + 1) <= '7') {
 +          if (flag_depth < ansi_depth) {
 +            safe_str(")]", value, &s);
 +            ansi_depth--;
 +          }
 +        } else {                /* ansi "flag", inverse, flash, underline, hilight */
 +          flag_depth = ansi_depth + 1;
 +        }
 +        /* Check to see if this is an 'ansi-reset' code. */
 +        if (*ptr == '0' && *(ptr + 1) == 'm') {
 +          for (; ansi_depth > 0; ansi_depth--) {
 +            safe_str(")]", value, &s);
 +          }
 +          flag_depth = 0;
 +          ptr++;
 +          break;
 +        }
 +
 +        ansi_depth++;
 +        safe_str("[ansi(", value, &s);
 +        dospace = 1;
 +
 +        /* code for decompiling ansi */
-         for (; isdigit(*ptr) || *ptr == ';'; ptr++) {
+       for (; isdigit((unsigned char) *ptr) || *ptr == ';'; ptr++) {
 -        if (*ptr == ';')      /* Yes, it is necessary to do it this way. */
 -          ptr++;
 -        /* Break if there is an 'm' here. */
 +          if (*ptr == ';')      /* Yes, it is necessary to do it this way. */
 +            ptr++;
 +          /* Break if there is an 'm' here. */
-           if (!*ptr || !isdigit(*ptr))
+         if (!*ptr || !isdigit((unsigned char) *ptr))
 -          break;
 -        /* Check to see if the code is one character long. */
 -        if (*(ptr + 1) == ';' || *(ptr + 1) == 'm') {
 -          /* ANSI flag */
 -          switch (*ptr) {
 -          case '1':
 -            safe_chr('h', value, &s);
 -            break;
 -          case '4':
 -            safe_chr('u', value, &s);
 -            break;
 -          case '5':
 -            safe_chr('f', value, &s);
 -            break;
 -          case '7':
 -            safe_chr('i', value, &s);
 -            break;
 -          default:            /* Not a valid code. */
 -            break;
 -          }
 -        } else {
 -          if (!*(ptr + 1))
 -            break;            /* Sudden string end or lack of real color code. */
 -          ptr++;
 -
 -          /* Check if this could be a real color (starts with 3 or 4) */
 -          if (*(ptr - 1) == '3' || *(ptr - 1) == '4') {
 -            switch (*ptr) {
 -            case '0':
 -              ansi_letter = 'x';
 -              break;
 -            case '1':
 -              ansi_letter = 'r';
 -              break;
 -            case '2':
 -              ansi_letter = 'g';
 -              break;
 -            case '3':
 -              ansi_letter = 'y';
 -              break;
 -            case '4':
 -              ansi_letter = 'b';
 -              break;
 -            case '5':
 -              ansi_letter = 'm';
 -              break;
 -            case '6': 
 -              ansi_letter = 'c';
 -              break;
 -            case '7':
 -              ansi_letter = 'w';
 -              break;
 -            default:
 -              break;          /* Not a valid color. */
 -            }
 -            /* If background color, change the letter to a capital. */
 -            if (*(ptr - 1) == '4')
 +            break;
 +          /* Check to see if the code is one character long. */
 +          if (*(ptr + 1) == ';' || *(ptr + 1) == 'm') {
 +            /* ANSI flag */
 +            switch (*ptr) {
 +            case '1':
 +              safe_chr('h', value, &s);
 +              break;
 +            case '4':
 +              safe_chr('u', value, &s);
 +              break;
 +            case '5':
 +              safe_chr('f', value, &s);
 +              break;
 +            case '7':
 +              safe_chr('i', value, &s);
 +              break;
 +            default:            /* Not a valid code. */
 +              break;
 +            }
 +          } else {
 +            if (!*(ptr + 1))
 +              break;            /* Sudden string end or lack of real color code. */
 +            ptr++;
 +
 +            /* Check if this could be a real color (starts with 3 or 4) */
 +            if (*(ptr - 1) == '3' || *(ptr - 1) == '4') {
 +              switch (*ptr) {
 +              case '0':
 +                ansi_letter = 'x';
 +                break;
 +              case '1':
 +                ansi_letter = 'r';
 +                break;
 +              case '2':
 +                ansi_letter = 'g';
 +                break;
 +              case '3':
 +                ansi_letter = 'y';
 +                break;
 +              case '4':
 +                ansi_letter = 'b';
 +                break;
 +              case '5':
 +                ansi_letter = 'm';
 +                break;
 +              case '6': 
 +                ansi_letter = 'c';
 +                break;
 +              case '7':
 +                ansi_letter = 'w';
 +                break;
 +              default:
 +                break;          /* Not a valid color. */
 +              }
 +              /* If background color, change the letter to a capital. */
 +              if (*(ptr - 1) == '4')
-                 ansi_letter = toupper(ansi_letter);
+               ansi_letter = UPCASE(ansi_letter);
 -            safe_chr(ansi_letter, value, &s);
 -          }
 -          /* No "else" here: If a two-digit code
 -           * doesn't start with 3 or 4, is isn't ANSI. */
 -        }
 -      }
 -      safe_chr(',', value, &s);
 +              safe_chr(ansi_letter, value, &s);
 +            }
 +            /* No "else" here: If a two-digit code
 +             * doesn't start with 3 or 4, is isn't ANSI. */
 +          }
 +        }
 +        safe_chr(',', value, &s);
        } else {
 -      ptr--;
 -      /* This shouldn't happen if we only have ansi codes
 -       * So if more dirty things must be added later... */
 +        ptr--;
 +        /* This shouldn't happen if we only have ansi codes
 +         * So if more dirty things must be added later... */
        }
        break;
      default:
diff --cc src/move.c
index 7f896938d8c2f23853919c1557156c4edcbe2327,a1a2dae02902b24d7be46c6af6a1d0294e2ec543..ca06adde8f5ba92ef7c7de39803f84ad745acde2
@@@ -95,38 -95,42 +95,42 @@@ moveit(dbref what, dbref where, int nom
      if ((where != NOTHING) && (old != where)) {
        did_it(what, what, NULL, NULL, "OXMOVE", NULL, NULL, old);
        if (Hearer(what) && !nomovemsgs) {
 -      did_it_interact(what, old, "LEAVE", NULL, "OLEAVE", T("has left."),
 -                      "ALEAVE", old, NA_INTER_PRESENCE);
 -      /* If the player is leaving a zone, do zone messages */
 -      /* The tricky bit here is that we only care about the zone of
 -       * the outermost contents */
 +        did_it_interact(what, old, "LEAVE", NULL, "OLEAVE", T("has left."),
 +                        "ALEAVE", old, NA_INTER_PRESENCE);
 +        /* If the player is leaving a zone, do zone messages */
 +        /* The tricky bit here is that we only care about the zone of
 +         * the outermost contents */
-         if (GoodObject(absold) && GoodObject(Zone(absold))
-             && (Zone(absloc) != Zone(absold)))
+         if (GoodObject(absloc) && GoodObject(Zone(absloc)) &&
+             (!GoodObject(absold) || !GoodObject(Zone(absold)) ||
+              (Zone(absloc) != Zone(absold))))
 -   did_it_interact(what, Zone(absold), "ZLEAVE", NULL, "OZLEAVE", NULL,
 -                        "AZLEAVE", old, NA_INTER_SEE);
 -      if (GoodObject(old) && !IsRoom(old))
 -        did_it_interact(what, old, NULL, NULL, "OXLEAVE", NULL, NULL, where,
 -                        NA_INTER_SEE);
 -      if (!IsRoom(where))
 -        did_it_interact(what, where, NULL, NULL, "OXENTER", NULL, NULL, old,
 -                        NA_INTER_SEE);
 -      /* If the player is entering a new zone, do zone messages */
 +          did_it_interact(what, Zone(absold), "ZLEAVE", NULL, "OZLEAVE", NULL,
 +                          "AZLEAVE", old, NA_INTER_SEE);
 +        if (GoodObject(old) && !IsRoom(old))
 +          did_it_interact(what, old, NULL, NULL, "OXLEAVE", NULL, NULL, where,
 +                          NA_INTER_SEE);
 +        if (!IsRoom(where))
 +          did_it_interact(what, where, NULL, NULL, "OXENTER", NULL, NULL, old,
 +                          NA_INTER_SEE);
 +        /* If the player is entering a new zone, do zone messages */
-         if (!GoodObject(absold)
-             || (GoodObject(Zone(absloc)) && (Zone(absloc) != Zone(absold))))
+         if (GoodObject(absloc) && GoodObject(Zone(absloc)) &&
+             (!GoodObject(absold) || !GoodObject(Zone(absold)) ||
+              (Zone(absloc) != Zone(absold))))
 -        did_it_interact(what, Zone(absloc), "ZENTER", NULL, "OZENTER", NULL,
 -            "AZENTER", where, NA_INTER_SEE);
 -      did_it_interact(what, where, "ENTER", NULL, "OENTER", T("has arrived."),
 -                      "AENTER", where, NA_INTER_PRESENCE);
 +          did_it_interact(what, Zone(absloc), "ZENTER", NULL, "OZENTER", NULL,
 +                          "AZENTER", where, NA_INTER_SEE);
 +        did_it_interact(what, where, "ENTER", NULL, "OENTER", T("has arrived."),
 +                        "AENTER", where, NA_INTER_PRESENCE);
        } else {
 -      /* non-listeners only trigger the actions not the messages */
 -      did_it(what, old, NULL, NULL, NULL, NULL, "ALEAVE", old);
 +        /* non-listeners only trigger the actions not the messages */
 +        did_it(what, old, NULL, NULL, NULL, NULL, "ALEAVE", old);
-         if (GoodObject(absold) && GoodObject(Zone(absold))
-             && (Zone(absloc) != Zone(absold)))
+         if (GoodObject(absold) && GoodObject(Zone(absold)) &&
+             (!GoodObject(absloc) || !GoodObject(Zone(absloc)) ||
+              (Zone(absloc) != Zone(absold))))
 -        did_it(what, Zone(absold), NULL, NULL, NULL, NULL, "AZLEAVE", old);
 +          did_it(what, Zone(absold), NULL, NULL, NULL, NULL, "AZLEAVE", old);
-         if (!GoodObject(absold)
-             || (GoodObject(Zone(absloc)) && (Zone(absloc) != Zone(absold))))
+         if (GoodObject(absloc) && GoodObject(Zone(absloc)) &&
+             (!GoodObject(absold) || !GoodObject(Zone(absold)) ||
+              (Zone(absloc) != Zone(absold))))
 -        did_it(what, Zone(absloc), NULL, NULL, NULL, NULL, "AZENTER", where);
 -      did_it(what, where, NULL, NULL, NULL, NULL, "AENTER", where);
 +          did_it(what, Zone(absloc), NULL, NULL, NULL, NULL, "AZENTER", where);
 +        did_it(what, where, NULL, NULL, NULL, NULL, "AENTER", where);
        }
      }
    if (!nomovemsgs)
diff --cc src/notify.c
index a260e8e4daa8d1ab1bf553fc8a7f065994c7e2e2,7ca7d7eebe260942473e2ae2a62d210ca9b60477..fa1b81ccd5c690195e4b5b4760e895548004106f
@@@ -918,57 -919,63 +918,63 @@@ notify_anything_loc(dbref speaker, na_l
      /* do @listen stuff */
      a = atr_get_noparent(target, "LISTEN");
      if (a) {
+       char match_space[BUFFER_LEN * 2];
+       int match_space_len = BUFFER_LEN * 2;
        if (!tbuf1)
 -      tbuf1 = (char *) mush_malloc(BUFFER_LEN, "string");
 +        tbuf1 = (char *) mush_malloc(BUFFER_LEN, "string");
        strcpy(tbuf1, atr_value(a));
        if (AF_Regexp(a)
-           ? regexp_match_case(tbuf1,
+         ? regexp_match_case_r(tbuf1,
 -                              (char *) notify_makestring(msgbuf, messages,
 +                              (char *) notify_makestring(msgbuf, messages,
-                                                          NA_ASCII), AF_Case(a))
-           : wild_match_case(tbuf1,
+                                                          NA_ASCII),
+                               AF_Case(a), global_eval_context.wnxt, 10,
+                               match_space, match_space_len)
+         : wild_match_case_r(tbuf1,
 -                            (char *) notify_makestring(msgbuf, messages,
 +                            (char *) notify_makestring(msgbuf, messages,
-                                                        NA_ASCII), AF_Case(a))) {
+                                                        NA_ASCII),
+                             AF_Case(a), global_eval_context.wnxt, 10,
+                             match_space, match_space_len)) {
 -      if (eval_lock(speaker, target, Listen_Lock))
 -        if (PLAYER_AHEAR || (!IsPlayer(target))) {
 -          if (speaker != target)
 -            charge_action(speaker, target, "AHEAR");
 -          else
 -            charge_action(speaker, target, "AMHEAR");
 -          charge_action(speaker, target, "AAHEAR");
 -        }
 -      if (!(flags & NA_NORELAY) && (loc != target) &&
 -          !filter_found(target,
 -                        (char *) notify_makestring(msgbuf, messages,
 -                                                   NA_ASCII), 1)) {
 -        passalong[0] = target;
 -        passalong[1] = target;
 -        passalong[2] = Owner(target);
 -        a = atr_get(target, "INPREFIX");
 -        if (a) {
 -          for (j = 0; j < 10; j++)
 -            wsave[j] = global_eval_context.wenv[j];
 -          global_eval_context.wenv[0] = (char *) msgbuf;
 -          for (j = 1; j < 10; j++)
 -            global_eval_context.wenv[j] = NULL;
 -          save_global_regs("inprefix_save", preserve);
 -          asave = safe_atr_value(a);
 -          ap = asave;
 -          bp = tbuf1;
 -          process_expression(tbuf1, &bp, &ap, target, speaker, speaker,
 -                             PE_DEFAULT, PT_DEFAULT, NULL);
 -          if (bp != tbuf1)
 -            safe_chr(' ', tbuf1, &bp);
 -          safe_str(msgbuf, tbuf1, &bp);
 -          *bp = 0;
 -          free(asave);
 -          restore_global_regs("inprefix_save", preserve);
 -          for (j = 0; j < 10; j++)
 -            global_eval_context.wenv[j] = wsave[j];
 -        }
 -        notify_anything(speaker, Puppet(target) ? na_except2 : na_except,
 -                        passalong, NULL, flags | NA_NORELAY | NA_PUPPET,
 -                        (a) ? tbuf1 : msgbuf);
 -      }
 +        if (eval_lock(speaker, target, Listen_Lock))
 +          if (PLAYER_AHEAR || (!IsPlayer(target))) {
 +            if (speaker != target)
 +              charge_action(speaker, target, "AHEAR");
 +            else
 +              charge_action(speaker, target, "AMHEAR");
 +            charge_action(speaker, target, "AAHEAR");
 +          }
 +        if (!(flags & NA_NORELAY) && (loc != target) &&
 +            !filter_found(target,
 +                          (char *) notify_makestring(msgbuf, messages,
 +                                                     NA_ASCII), 1)) {
 +          passalong[0] = target;
 +          passalong[1] = target;
 +          passalong[2] = Owner(target);
 +          a = atr_get(target, "INPREFIX");
 +          if (a) {
 +            for (j = 0; j < 10; j++)
 +              wsave[j] = global_eval_context.wenv[j];
 +            global_eval_context.wenv[0] = (char *) msgbuf;
 +            for (j = 1; j < 10; j++)
 +              global_eval_context.wenv[j] = NULL;
 +            save_global_regs("inprefix_save", preserve);
 +            asave = safe_atr_value(a);
 +            ap = asave;
 +            bp = tbuf1;
 +            process_expression(tbuf1, &bp, &ap, target, speaker, speaker,
 +                               PE_DEFAULT, PT_DEFAULT, NULL);
 +            if (bp != tbuf1)
 +              safe_chr(' ', tbuf1, &bp);
 +            safe_str(msgbuf, tbuf1, &bp);
 +            *bp = 0;
 +            free(asave);
 +            restore_global_regs("inprefix_save", preserve);
 +            for (j = 0; j < 10; j++)
 +              global_eval_context.wenv[j] = wsave[j];
 +          }
 +          notify_anything(speaker, Puppet(target) ? na_except2 : na_except,
 +                          passalong, NULL, flags | NA_NORELAY | NA_PUPPET,
 +                          (a) ? tbuf1 : msgbuf);
 +        }
        }
      }
      /* if object is flagged LISTENER, check for ^ listen patterns
diff --cc src/parse.c
index 3f8e217929eb338bda086c252e3c2ac410bbab09,334d3e816811fe3253f2906e5b78760204321514..3d8b8ee4cba7d125421e20497ed4326652509825
@@@ -746,148 -767,148 +767,148 @@@ process_expression(char *buff, char **b
              (*str)++;
            }
            break;
 -      case 'V':
 -      case 'v':
 -      case 'W':
 -      case 'w':
 -      case 'X':
 -      case 'x':
 -        /* These sequences escape two characters */
 -        savec = **str;
 -        if (!savec)
 -          goto exit_sequence;
 -        safe_chr(savec, buff, bp);
 -        (*str)++;
 -      }
 -      break;
 +        case 'V':
 +        case 'v':
 +        case 'W':
 +        case 'w':
 +        case 'X':
 +        case 'x':
 +          /* These sequences escape two characters */
 +          savec = **str;
 +          if (!savec)
 +            goto exit_sequence;
 +          safe_chr(savec, buff, bp);
 +          (*str)++;
 +        }
 +        break;
        } else {
 -      char savec, nextc;
 -      char *savepos;
 -      ATTR *attrib;
 +        char savec, nextc;
 +        char *savepos;
 +        ATTR *attrib;
  
 -      (*str)++;
 -      savec = **str;
 -      if (!savec) {
 -        /* Line ended in %, so treat it as a literal */
 -        safe_chr('%', buff, bp);
 -        goto exit_sequence;
 -      }
 -      savepos = *bp;
 -      (*str)++;
 +        (*str)++;
 +        savec = **str;
 +        if (!savec) {
 +          /* Line ended in %, so treat it as a literal */
 +          safe_chr('%', buff, bp);
 +          goto exit_sequence;
 +        }
 +        savepos = *bp;
 +        (*str)++;
  
 -      switch (savec) {
 -      case '%':               /* %% - a real % */
 -        safe_chr('%', buff, bp);
 -        break;
 -      case ' ':               /* "% " for more natural typing */
 -        safe_str("% ", buff, bp);
 -        break;
 -      case '!':               /* executor dbref */
 -        safe_dbref(executor, buff, bp);
 -        break;
 -      case '@':               /* caller dbref */
 -        safe_dbref(caller, buff, bp);
 -        break;
 -      case '#':               /* enactor dbref */
 -        safe_dbref(enactor, buff, bp);
 -        break;
 -      case ':':               /* enactor unique id */
 -        safe_dbref(enactor, buff, bp);
 -        safe_chr(':', buff, bp);
 -        safe_integer(CreTime(enactor), buff, bp);
 -        break;
 -      case '?':               /* function limits */
 -        if (pe_info) {
 -          safe_integer(pe_info->fun_invocations, buff, bp);
 -          safe_chr(' ', buff, bp);
 -          safe_integer(pe_info->fun_depth, buff, bp);
 -        } else {
 -          safe_str("0 0", buff, bp);
 -        }
 -        break;
 -      case '~':               /* enactor accented name */
 -        safe_str(accented_name(enactor), buff, bp);
 -        break;
 -      case '+':               /* argument count */
 -        if (pe_info)
 -          safe_integer(pe_info->arg_count, buff, bp);
 -        else
 -          safe_integer(0, buff, bp);
 -        break;
 -      case '0':
 -      case '1':
 -      case '2':
 -      case '3':
 -      case '4':
 -      case '5':
 -      case '6':
 -      case '7':
 -      case '8':
 -      case '9':               /* positional argument */
 -        if (global_eval_context.wenv[savec - '0'])
 -          safe_str(global_eval_context.wenv[savec - '0'], buff, bp);
 -        break;
 -      case 'A':
 -      case 'a':               /* enactor absolute possessive pronoun */
 -        if (gender < 0)
 -          gender = get_gender(enactor);
 -        safe_str(absp[gender], buff, bp);
 -        break;
 -      case 'B':
 -      case 'b':               /* blank space */
 -        safe_chr(' ', buff, bp);
 -        break;
 -      case 'C':
 -      case 'c':               /* command line */
 -        safe_str(global_eval_context.ccom, buff, bp);
 -        break;
 -      case 'I':
 -      case 'i':
 -        nextc = **str;
 -        if (!nextc)
 -          goto exit_sequence;
 -        (*str)++;
 +        switch (savec) {
 +        case '%':               /* %% - a real % */
 +          safe_chr('%', buff, bp);
 +          break;
 +        case ' ':               /* "% " for more natural typing */
 +          safe_str("% ", buff, bp);
 +          break;
 +        case '!':               /* executor dbref */
 +          safe_dbref(executor, buff, bp);
 +          break;
 +        case '@':               /* caller dbref */
 +          safe_dbref(caller, buff, bp);
 +          break;
 +        case '#':               /* enactor dbref */
 +          safe_dbref(enactor, buff, bp);
 +          break;
 +        case ':':               /* enactor unique id */
 +          safe_dbref(enactor, buff, bp);
 +          safe_chr(':', buff, bp);
 +          safe_integer(CreTime(enactor), buff, bp);
 +          break;
 +        case '?':               /* function limits */
 +          if (pe_info) {
 +            safe_integer(pe_info->fun_invocations, buff, bp);
 +            safe_chr(' ', buff, bp);
 +            safe_integer(pe_info->fun_depth, buff, bp);
 +          } else {
 +            safe_str("0 0", buff, bp);
 +          }
 +          break;
 +        case '~':               /* enactor accented name */
 +          safe_str(accented_name(enactor), buff, bp);
 +          break;
 +        case '+':               /* argument count */
 +          if (pe_info)
 +            safe_integer(pe_info->arg_count, buff, bp);
 +          else
 +            safe_integer(0, buff, bp);
 +          break;
 +        case '0':
 +        case '1':
 +        case '2':
 +        case '3':
 +        case '4':
 +        case '5':
 +        case '6':
 +        case '7':
 +        case '8':
 +        case '9':               /* positional argument */
 +          if (global_eval_context.wenv[savec - '0'])
 +            safe_str(global_eval_context.wenv[savec - '0'], buff, bp);
 +          break;
 +        case 'A':
 +        case 'a':               /* enactor absolute possessive pronoun */
 +          if (gender < 0)
 +            gender = get_gender(enactor);
 +          safe_str(absp[gender], buff, bp);
 +          break;
 +        case 'B':
 +        case 'b':               /* blank space */
 +          safe_chr(' ', buff, bp);
 +          break;
 +        case 'C':
 +        case 'c':               /* command line */
 +          safe_str(global_eval_context.ccom, buff, bp);
 +          break;
 +        case 'I':
 +        case 'i':
 +          nextc = **str;
 +          if (!nextc)
 +            goto exit_sequence;
 +          (*str)++;
-           if (!isdigit(nextc)) {
+         if (!isdigit((unsigned char) nextc)) {
 -          safe_str(T(e_int), buff, bp);
 -          break;
 -        }
 -        inum_this = nextc - '0';
 -        if (inum_this < 0 || inum_this >= inum
 -            || (inum - inum_this) <= inum_limit) {
 -          safe_str(T("#-1 ARGUMENT OUT OF RANGE"), buff, bp);
 -        } else {
 -          safe_str(iter_rep[inum - inum_this], buff, bp);
 -        }
 -        break;
 -      case 'U':
 -      case 'u':
 -        safe_str(global_eval_context.ucom, buff, bp);
 -        break;
 -      case 'L':
 -      case 'l':               /* enactor location dbref */
 -        /* The security implications of this have
 -         * already been talked to death.  Deal. */
 -        safe_dbref(Location(enactor), buff, bp);
 -        break;
 -      case 'N':
 -      case 'n':               /* enactor name */
 -        safe_str(Name(enactor), buff, bp);
 -        break;
 -      case 'O':
 -      case 'o':               /* enactor objective pronoun */
 -        if (gender < 0)
 -          gender = get_gender(enactor);
 -        safe_str(obj[gender], buff, bp);
 -        break;
 -      case 'P':
 -      case 'p':               /* enactor possessive pronoun */
 -        if (gender < 0)
 -          gender = get_gender(enactor);
 -        safe_str(poss[gender], buff, bp);
 -        break;
 +            safe_str(T(e_int), buff, bp);
 +            break;
 +          }
 +          inum_this = nextc - '0';
 +          if (inum_this < 0 || inum_this >= inum
 +              || (inum - inum_this) <= inum_limit) {
 +            safe_str(T("#-1 ARGUMENT OUT OF RANGE"), buff, bp);
 +          } else {
 +            safe_str(iter_rep[inum - inum_this], buff, bp);
 +          }
 +          break;
 +        case 'U':
 +        case 'u':
 +          safe_str(global_eval_context.ucom, buff, bp);
 +          break;
 +        case 'L':
 +        case 'l':               /* enactor location dbref */
 +          /* The security implications of this have
 +           * already been talked to death.  Deal. */
 +          safe_dbref(Location(enactor), buff, bp);
 +          break;
 +        case 'N':
 +        case 'n':               /* enactor name */
 +          safe_str(Name(enactor), buff, bp);
 +          break;
 +        case 'O':
 +        case 'o':               /* enactor objective pronoun */
 +          if (gender < 0)
 +            gender = get_gender(enactor);
 +          safe_str(obj[gender], buff, bp);
 +          break;
 +        case 'P':
 +        case 'p':               /* enactor possessive pronoun */
 +          if (gender < 0)
 +            gender = get_gender(enactor);
 +          safe_str(poss[gender], buff, bp);
 +          break;
          case '<':
 -        if (!**str)
 -          goto exit_sequence;
 +          if (!**str)
 +            goto exit_sequence;
            {
              const char *tmp;
              char atrname[BUFFER_LEN];
diff --cc src/player.c
index 77422430920fd154ea0bff8e2ca8fec5b5f9aacc,eb6d7999ccfe011bc8d8c60358e87e7a5e1202bc..6ebdeb0a6ef4163b4e8747e3b2500e4c8d8602ed
@@@ -190,52 -187,52 +190,52 @@@ connect_player(const char *name, const 
   */
  
  dbref create_guest(const char *host, const char *ip) {
 -      int i , mg;
 -      char *guest_name;
 -      dbref gst_id;
 -
 -      mg = MAX_GUESTS == 0 ? 100 : MAX_GUESTS;
 -      guest_name = (char *) mush_malloc(BUFFER_LEN, "gst_buf");
 -      gst_id = NOTHING;
 -
 -      for( i = 0 ; i  < mg ; i++)  {
 -              /* reset vars */
 -              memset(guest_name, '\0', BUFFER_LEN);
 -              gst_id = NOTHING;  
 -              strncpy(guest_name, T(GUEST_PREFIX), BUFFER_LEN-1);
 -              strcat(guest_name, GUEST_NUMBER(i+1));
 -              if(ok_player_name(guest_name, NOTHING, NOTHING))
 -                break;        
 -              else if((gst_id = lookup_player(guest_name)) != NOTHING && !Connected(gst_id))
 -                      break;
 -              else continue;
 -      }
 -      if(gst_id == NOTHING) {
 -        if(i >= mg)  {
 -              mush_free((Malloc_t) guest_name, "gst_buf");
 -              return NOTHING;
 -        } else if(DBTOP_MAX && (db_top >= DBTOP_MAX + 1) && (first_free == NOTHING)) {
 -              mush_free((Malloc_t) guest_name, "gst_buf");
 -              do_log(LT_CONN, 0, 0, T("Failed creation (no db space) from %s"), host);
 -              return NOTHING;
 -        }
 -        gst_id = make_player(guest_name, "", host, ip);
 -      } else  { /* Reset Guest */
 -              object_flag_type flags;
 -              flags = string_to_bits("FLAG", options.player_flags);
 -              copy_flag_bitmask("FLAG", Flags(gst_id), flags);
 -      }
 -      mush_free((Malloc_t) guest_name, "gst_buf");
 +        int i , mg;
 +        char *guest_name;
 +        dbref gst_id;
 +
 +        mg = MAX_GUESTS == 0 ? 100 : MAX_GUESTS;
 +        guest_name = (char *) mush_malloc(BUFFER_LEN, "gst_buf");
 +        gst_id = NOTHING;
 +
 +        for( i = 0 ; i  < mg ; i++)  {
 +                /* reset vars */
 +                memset(guest_name, '\0', BUFFER_LEN);
 +                gst_id = NOTHING;  
 +                strncpy(guest_name, T(GUEST_PREFIX), BUFFER_LEN-1);
 +                strcat(guest_name, GUEST_NUMBER(i+1));
 +                if(ok_player_name(guest_name, NOTHING, NOTHING))
 +                  break;        
 +                else if((gst_id = lookup_player(guest_name)) != NOTHING && !Connected(gst_id))
 +                        break;
 +                else continue;
 +        }
 +        if(gst_id == NOTHING) {
 +          if(i >= mg)  {
 +                mush_free((Malloc_t) guest_name, "gst_buf");
 +                return NOTHING;
 +          } else if(DBTOP_MAX && (db_top >= DBTOP_MAX + 1) && (first_free == NOTHING)) {
 +                mush_free((Malloc_t) guest_name, "gst_buf");
 +                do_log(LT_CONN, 0, 0, T("Failed creation (no db space) from %s"), host);
 +                return NOTHING;
 +          }
 +          gst_id = make_player(guest_name, "", host, ip);
 +        } else  { /* Reset Guest */
 +                object_flag_type flags;
 +                flags = string_to_bits("FLAG", options.player_flags);
 +                copy_flag_bitmask("FLAG", Flags(gst_id), flags);
 +        }
 +        mush_free((Malloc_t) guest_name, "gst_buf");
-         atr_add(gst_id, "DESCRIBE", GUEST_DESCRIBE, gst_id, NOTHING);
+       atr_add(gst_id, "DESCRIBE", GUEST_DESCRIBE, gst_id, 0);
  
 -      SLEVEL(gst_id) = LEVEL_GUEST;
 -      Home(gst_id) = options.guest_start;
 -      if(GoodObject(options.guest_start) && IsRoom(options.guest_start)) {
 -        Contents(Location(gst_id)) = remove_first(Contents(Location(gst_id)), gst_id);
 -        Location(gst_id) = GUEST_START;
 -        PUSH(gst_id, Contents(options.guest_start));
 -      }
 -      return gst_id;
 +        SLEVEL(gst_id) = LEVEL_GUEST;
 +        Home(gst_id) = options.guest_start;
 +        if(GoodObject(options.guest_start) && IsRoom(options.guest_start)) {
 +          Contents(Location(gst_id)) = remove_first(Contents(Location(gst_id)), gst_id);
 +          Location(gst_id) = GUEST_START;
 +          PUSH(gst_id, Contents(options.guest_start));
 +        }
 +        return gst_id;
  }
  /** Attempt to create a new player object.
   * \param name name of player to create.
@@@ -437,19 -429,19 +435,19 @@@ make_player(const char *name, const cha
    set_initial_warnings(player);
    /* Modtime tracks login failures */
    ModTime(player) = (time_t) 0;
-   (void) atr_add(player, "XYXXY", mush_crypt(password), GOD, NOTHING);
+   (void) atr_add(player, "XYXXY", mush_crypt(password), GOD, 0);
    giveto(player, START_BONUS);  /* starting bonus */
-   (void) atr_add(player, "LAST", show_time(mudtime, 0), GOD, NOTHING);
-   (void) atr_add(player, "LASTSITE", host, GOD, NOTHING);
-   (void) atr_add(player, "LASTIP", ip, GOD, NOTHING);
-   (void) atr_add(player, "LASTFAILED", " ", GOD, NOTHING);
+   (void) atr_add(player, "LAST", show_time(mudtime, 0), GOD, 0);
+   (void) atr_add(player, "LASTSITE", host, GOD, 0);
+   (void) atr_add(player, "LASTIP", ip, GOD, 0);
+   (void) atr_add(player, "LASTFAILED", " ", GOD, 0);
    sprintf(temp, "%d", START_QUOTA);
-   (void) atr_add(player, "RQUOTA", temp, GOD, NOTHING);
+   (void) atr_add(player, "RQUOTA", temp, GOD, 0);
    (void) atr_add(player, "ICLOC", EMPTY_ATTRS ? "" : " ", GOD,
 -               AF_MDARK | AF_PRIVATE | AF_NOCOPY);
 +                 AF_MDARK | AF_PRIVATE | AF_NOCOPY);
  #ifdef USE_MAILER
    (void) atr_add(player, "MAILCURF", "0", GOD,
 -               AF_LOCKED | AF_NOPROG);
 +                 AF_LOCKED | AF_NOPROG);
    add_folder_name(player, 0, "inbox");
  #endif
    /* link him to PLAYER_START */
diff --cc src/predicat.c
Simple merge
diff --cc src/prog.c
Simple merge
diff --cc src/services.c
Simple merge
diff --cc src/set.c
index d4fca916373fc2033e235b400a402dda889a236a,f13cc208975eb2f4d0e1b6ebb39b533c778def05..2f378fcc5b1c16a897623d6f34e812da3d316353
+++ b/src/set.c
@@@ -1084,9 -1084,26 +1084,26 @@@ wipe_helper(dbref player, dbref thing, 
     * attributes using this command and wildcards.  Wiping a specific
     * attr still works, though.
     */
+   int saved_count = AttrCount(thing);
+  
    if (wildcard(pattern) && (AL_FLAGS(atr) & AF_PRIVILEGE) && !Director(player))
 -        return 0;
 +          return 0;
-   return do_set_atr(thing, AL_NAME(atr), NULL, player, 0) == 1;
+   switch (wipe_atr(thing, AL_NAME(atr), player)) {
+   case AE_SAFE:
+     notify_format(player, T("Attribute %s is SAFE. Set it !SAFE to modify it."),
+                 AL_NAME(atr));
+     return 0;
+   case AE_ERROR:
+     notify_format(player, T("Unable to wipe attribute %s"), AL_NAME(atr));
+     return 0;
+   case AE_TREE:
+     notify_format(player,
+                 T("Attribute %s cannot be wiped because a child attribute cannot be wiped."),
+                 AL_NAME(atr));
+     /* Fall through */
+   default:
+     return saved_count - AttrCount(thing);
+  }
  }
  
  /** Clear an attribute.
diff --cc src/speech.c
Simple merge
diff --cc src/sql.c
Simple merge
diff --cc src/strutil.c
Simple merge
diff --cc src/timer.c
index 95aed0a0bb1172b8c28a8e9f810b0f81a4a7ae7f,257db5d60e2cba6838d402e50d7085b3c100d53d..8fee2d022d50280ad79f531cffc67152e488d2de
  #include "game.h"
  #include "help.h"
  #include "parse.h"
+ #include "attrib.h"
  #include "confmagic.h"
 +#include "modules.h"
  
 +/* Module extern */
 +extern struct module_entry_t *module_list;
  
  static sig_atomic_t hup_triggered = 0;
  static sig_atomic_t usr1_triggered = 0;
diff --cc src/unparse.c
index e679d9c099f1edbbbe5b1feb2db483d2ce34c173,29a85c8685f2784578714f67a1645da5cfa764f7..ac01c5e6692b0f6a839776f6c5e54ea73c89b03a
@@@ -145,29 -144,27 +144,27 @@@ real_unparse(dbref player, dbref loc, i
      }
      /* Don't let 'em get dbrefs when they're IC */
      if ((Can_Examine(player, loc) || can_link_to(player, loc) ||
 -       JumpOk(loc) || ChownOk(loc) || DestOk(loc)) &&
 +         JumpOk(loc) || ChownOk(loc) || DestOk(loc)) &&
-         (!Myopic(player) || !obey_myopic) &&
-         !(use_nameformat && got_nameformat)
-         ) {
+       (!Myopic(player) || !obey_myopic)) {
        /* show everything */
        if (SUPPORT_PUEBLO)
 -      couldunparse = 1;
 +        couldunparse = 1;
        bp = buf;
-       if (ANSI_NAMES && ShowAnsi(player) && !got_nameformat)
+       if (ANSI_NAMES && ShowAnsi(player))
 -      safe_format(buf, &bp, "%s%s%s(#%d%s)", ANSI_HILITE, tbuf1,
 -                  ANSI_NORMAL, loc, unparse_flags(loc, player));
 +        safe_format(buf, &bp, "%s%s%s(#%d%s)", ANSI_HILITE, tbuf1,
 +                    ANSI_NORMAL, loc, unparse_flags(loc, player));
        else
 -      safe_format(buf, &bp, "%s(#%d%s)", tbuf1, loc,
 -                  unparse_flags(loc, player));
 +        safe_format(buf, &bp, "%s(#%d%s)", tbuf1, loc,
 +                    unparse_flags(loc, player));
        *bp = '\0';
      } else {
        /* show only the name */
-       if (ANSI_NAMES && ShowAnsi(player) && !got_nameformat) {
+       if (ANSI_NAMES && ShowAnsi(player)) {
 -      bp = buf;
 -      safe_format(buf, &bp, "%s%s%s", ANSI_HILITE, tbuf1, ANSI_NORMAL);
 -      *bp = '\0';
 +        bp = buf;
 +        safe_format(buf, &bp, "%s%s%s", ANSI_HILITE, tbuf1, ANSI_NORMAL);
 +        *bp = '\0';
        } else
 -      strcpy(buf, tbuf1);
 +        strcpy(buf, tbuf1);
      }
    }
    /* buf now contains the default formatting of the name. If we
diff --cc src/utils.c
Simple merge
diff --cc src/wild.c
index 51d2240ea64a0c34c60c866e9a5273eb7f3e294f,66efbf08cac4887d471284e557659a3a6b533af1..48a0569af2c62a5ace6a1931d58637cf07546b34
@@@ -388,21 -398,31 +398,31 @@@ wild1(const char *RESTRICT tstr, const 
    /* Found a match!  Fill in all remaining arguments.
     * First do the '*'...
     */
-   global_eval_context.wnxt[argpos++] = wbuf;
-   strncpy(wbuf, datapos, (dstr - datapos) - numextra);
-   wbuf += (dstr - datapos) - numextra;
-   *wbuf++ = '\0';
+   {
+     int datalen;
+     datalen = (dstr - datapos) - numextra;
+     if (datalen + 1 <= *len) {
+       ary[argpos++] = *wbuf;
+       strncpy(*wbuf, datapos, datalen);
+       *wbuf += datalen;
+       *(*wbuf)++ = '\0';
+       *len -= datalen + 1;
 -      datapos = dstr - numextra;
 +  datapos = dstr - numextra;
+     }
+   }
  
    /* Fill in any trailing '?'s that are left. */
    while (numextra) {
-     if (argpos >= NUMARGS)
+     if (argpos >= (int) max || *len < 2)
        return 1;
-     global_eval_context.wnxt[argpos++] = wbuf;
-     *wbuf++ = *datapos++;
-     *wbuf++ = '\0';
+     if (*len >= 2) {
+       ary[argpos++] = *wbuf;
+       *(*wbuf)++ = *datapos++;
+       *(*wbuf)++ = '\0';
+       *len -= 2;
 -      numextra--;
 -    }
 +    numextra--;
 +  }
+   }
  
    /* It's done! */
    return 1;
@@@ -437,11 -459,12 +459,12 @@@ wild(const char *RESTRICT s, const cha
      return 0;
  
    /* Do the match. */
-   return wild1(s, d, p, wspace, cs);
+   return wild1(s, d, p, &buffer, &len, cs, ary, max);
  }
 - 
 +
- /** Wildcard match, possibly case-sensitive, and remember the wild data.
-  *
+ /** Wildcard match, possibly case-sensitive, and remember the wild data
+  *  in matches, storing them in data.
   * This routine will cause crashes if fed NULLs instead of strings.
   *
   * \param s pattern to match against.
@@@ -596,22 -635,25 +635,25 @@@ quick_regexp_match(const char *RESTRIC
  int
  local_wild_match_case(const char *RESTRICT s, const char *RESTRICT d, int cs)
  {
 -    switch (*s) {
 -    case '>':
 -      s++;
 -      if (is_number(s) && is_number(d))
 -        return (parse_number(s) < parse_number(d));
 -      else
 -        return (strcoll(s, d) < 0);
 -    case '<':
 -      s++;
 -      if (is_number(s) && is_number(d))
 -        return (parse_number(s) > parse_number(d));
 -      else
 -        return (strcoll(s, d) > 0);
+   if (s && *s) {
-   }
 +  switch (*s) {
 +  case '>':
 +    s++;
 +    if (is_number(s) && is_number(d))
 +      return (parse_number(s) < parse_number(d));
 +    else
 +      return (strcoll(s, d) < 0);
 +  case '<':
 +    s++;
 +    if (is_number(s) && is_number(d))
 +      return (parse_number(s) > parse_number(d));
 +    else
 +      return (strcoll(s, d) > 0);
 -      return quick_wild_new(s, d, cs);
+     default:
 +  return quick_wild_new(s, d, cs);
+     }
+   } else
+     return (!d || !*d) ? 1 : 0;
  }
  
  /** Does a string contain a wildcard character (* or ?)?
diff --cc src/wiz.c
index 1efd2dcaf442377c7e9d6daabedc6e6ca71f0bb2,b159ccce65bb6cd9f9284c562ab61549f4e21cdf..267225cd6c668623f0a2563c02d31050bdbf03cc
+++ b/src/wiz.c
@@@ -284,10 -284,10 +284,10 @@@ do_allquota(dbref player, const char *a
      }
      if (limit != -1) {
        if (limit <= owned) {
-         (void) atr_add(who, "RQUOTA", "0", GOD, NOTHING);
+       (void) atr_add(who, "RQUOTA", "0", GOD, 0);
        } else {
 -      (void) atr_add(who, "RQUOTA", tprintf("%d", limit - owned), GOD,
 +        (void) atr_add(who, "RQUOTA", tprintf("%d", limit - owned), GOD,
-                        NOTHING);
+                      0);
        }
      }
    }
@@@ -811,10 -811,10 +811,10 @@@ do_newpassword(dbref player, dbref caus
        notify(player, T("Bad password."));
      } else {
        /* it's ok, do it */
-       (void) atr_add(victim, "XYXXY", mush_crypt(password), GOD, NOTHING);
+       (void) atr_add(victim, "XYXXY", mush_crypt(password), GOD, 0);
        notify_format(player, T("Password for %s changed."), Name(victim));
        notify_format(victim, T("Your password has been changed by %s."),
 -                  Name(player));
 +                    Name(player));
        do_log(LT_WIZ, player, victim, "*** NEWPASSWORD ***");
      }
    } else {
@@@ -1782,14 -1785,15 +1785,15 @@@ fill_search_spec(dbref player, const ch
        spec->low = parse_integer(class + offset);
        if (!GoodObject(spec->low))
        spec->low = 0;
-       if (isdigit(*restriction) || ((*restriction == '#') && *(restriction + 1)
-                                     && isdigit(*(restriction + 1)))) {
+       if (isdigit((unsigned char) *restriction)
+         || ((*restriction == '#') && *(restriction + 1)
+             && isdigit((unsigned char) *(restriction + 1)))) {
 -      offset = 0;
 -      if (*restriction == '#')
 -        offset = 1;
 -      spec->high = parse_integer(restriction + offset);
 -      if (!GoodObject(spec->high))
 -        spec->high = db_top - 1;
 +        offset = 0;
 +        if (*restriction == '#')
 +          offset = 1;
 +        spec->high = parse_integer(restriction + offset);
 +        if (!GoodObject(spec->high))
 +          spec->high = db_top - 1;
        }
        continue;
      }
index f0e2ad0af935e3e9a455a1897c96b200c6900ae8,41078c933d33ab7b0c8afd84d3ca6323cb5ea9ca..c156c318916e42a5018240aecdd4fa2dee9a9a83
@@@ -45,5 -42,8 +45,7 @@@ for i in hlp nws evt ; d
      cd ..
  done
  
- cd ../..
+ # Step 6: Create connect.txt file
+ cd ../../
+ ( utils/makeconnect.sh ; mv connect.txt game/txt )
  
 -