portions pertaining to visual studio project files not applied.
Untested
checkin: versions autogen
@prcs checkin
+commit: indent
+ @svn commit
+
patch: versions
@make-patch-header
@make diffs
at http://pennmush.org/~alansz/guide.html
or by ftp from pennmush.org, /pub/PennMUSH/Guide
============================================================================
-
+
I. Introduction and history
PennMUSH uses a version-numbering system that includes version
numbers (like 1.7.2) and patchlevels (like p32), usually written
-together (1.7.2p32).
+together (1.7.2p32).
Starting with 1.7.2, version numbers that are even (like 1.7.2) are
stable releases - patchlevels on the latest stable release will only be
TinyMUSH 2.0.
In January of 1995, Amberyl passed on her mantle to Javelin (aka
-Paul@Dune, Alan Schwartz), who is now the maintainer of the primary
-public distribution in development. He released two patchlevels
+Paul@Dune, Alan Schwartz), who continuted as the maintainer of the
+primary public distribution in development. He released two patchlevels
numbered "dune-1" and "dune-2" before releasing PennMUSH 1.50 pl11 and
later distributions. The numbering scheme changed again with PennMUSH
1.6.0 (see CHANGES.OLD).
simultaneously adopted by TinyMUSH (2.2.5, 3.x) and TinyMUX to
facilitate code sharing and widen use.
+In July 2006, Javelin retired from the role of Maintainer, passing the
+mantle of lead developer to Raevnos and that of release management to
+Ervin Hearn (Noltar). Many thanks go to Javelin whose contributions and
+guidance of PennMUSH have shaped it into the codebase that it is today.
+
A MUSH manual should be available at ftp.digex.net, ftp.math.okstate.edu,
primerd.prime.com, or from wherever you got this code from. The manual
should be numbered version 2.007 or higher.
informed of new patches, subscribe to pennmush-announce instead,
at http://www.pennmush.org/mailman/listinfo/pennmush-announce)
-2. pennmush-bugs@pennmush.org is the bug reporting address
+2. pennmush-bugs@pennmush.org is the bug reporting address
for the PennMUSH developers (suggestions go to pennmush-developers,
bugs to pennmush-bugs). This will generally give you the fastest
response and is ideal for unusual bugs. A web-based submission
3. The operating system and version (SunOS 4.1.2, AIX 3.2.4, etc.),
4. The compiler and compiler version (gcc 2.4.5, SGI cc 2.10, etc. -- the
'file' command usually tells you the compiler version, if there's no
- built-in option like '-v' or '-V' to give it),
+ built-in option like '-v' or '-V' to give it),
5. Whether or not you have made any changes to the code.
If the problem resulted in a crash and a core dump, a stack trace of
so players don't need to telnet to obscuresite.obscuredomain.com!
NOTE: A hostname is not the same thing as a site. We don't have accounts
-for you to run your MUSH from. You must already have your MUSH
+for you to run your MUSH from. You must already have your MUSH
running at someplace.edu or whatever -- we just provide a nice hostname
that will resolve into your current site's IP address.
-How do you get a pennmush.org hostname? Go to
-http://lists.pennmush.org/pennmush.html, and follow the instructions.
+How do you get a pennmush.org hostname? Go to
+http://services.pennmush.org/, and follow the instructions.
It may take a day or two before the hostname will work.
Thovald also has volunteered to host mailing lists for MUSHes in
============================================================================
IV. Comments
-
+
IV.a. Amberyl's Comments
These are in the first person. :)
-
+
I've been working with this code for a year and a quarter now. I can't
claim that it's particularly elegant or inspired; all I can say is that
it works (most of the time), and that I've had fun writing it. I'm
int last_hval; /**< State for hashfirst & hashnext. */
HASHENT *last_entry; /**< State for hashfirst & hashnext. */
int entry_size; /**< Size of each entry */
- void (*free_data)(void*); /**< Function to call on data when deleting
- a entry. */
+ void (*free_data) (void *); /**< Function to call on data when deleting
+ a entry. */
};
#define get_hashmask(x) hash_getmask(x)
#define hashflush(tab, size) hash_flush(tab,size)
#define hashfree(tab) hash_flush(tab, 0)
extern int hash_getmask(int *size);
-extern void hash_init(HASHTAB *htab, int size, int data_size, void (*)(void*));
+extern void hash_init(HASHTAB *htab, int size, int data_size, void (*)(void *));
extern HASHENT *hash_find(HASHTAB *htab, const char *key);
extern void *hash_value(HASHENT *entry);
extern char *hash_key(HASHENT *entry);
command_check(dbref player, COMMAND_INFO *cmd, switch_mask switches)
{
int ok;
- char *mess = NULL;
+ const char *mess = NULL;
/* God doesn't get fucked with */
if(LEVEL(player) >= LEVEL_GOD)
,
{"ssl_ip_addr", cf_str, options.ssl_ip_addr, 64, 0, "net"}
,
- {"port", cf_int, &options.port, 32000, 0, "net"}
+ {"port", cf_int, &options.port, 65535, 0, "net"}
,
- {"ssl_port", cf_int, &options.ssl_port, 32000, 0, "net"}
+ {"ssl_port", cf_int, &options.ssl_port, 65535, 0, "net"}
,
{"use_dns", cf_bool, &options.use_dns, 2, 0, "net"}
,
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);
void init_qids();
int create_qid();
* they're due to expire; semaphore queue entries are just added
* to the back of the queue.
* \param player the enqueuing object.
- * \param wait time to wait, or 0.
+ * \param waittill time to wait, or 0.
* \param command command to enqueue.
* \param cause object that caused command to be enqueued.
* \param sem object to serve as a semaphore, or NOTHING.
* \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)
{
BQUE *tmp;
int a, qid;
- if (wait == 0) {
+ if (waittill == 0) {
if (sem != NOTHING)
add_to_sem(sem, -1, semattr);
parse_que(player, command, cause);
copy_namedregs(&tmp->namedregs, &global_eval_context.namedregs);
if (until) {
- tmp->left = wait;
+ tmp->left = waittill;
} else {
- if (wait >= 0)
- tmp->left = mudtime + wait;
+ if (waittill >= 0)
+ tmp->left = mudtime + waittill;
else
tmp->left = 0; /* semaphore wait without a timeout */
}
}
for (;;) {
- int c;
+ int ch;
- c = fgetc(f);
- ungetc(c, f);
+ ch = fgetc(f);
+ ungetc(ch, f);
- if (c != ' ')
+ if (ch != ' ')
break;
found++;
add_lock_raw(creator, i, type, b, flags);
}
- if (found != count)
+ if (found != count)
do_rawlog(LT_ERR,
- T("WARNING: Actual lock count (%d) different from expected count (%d)."),
- found, count);
+ T
+ ("WARNING: Actual lock count (%d) different from expected count (%d)."),
+ found, count);
}
}
static void
-init_objdata_htab(int size, void (*free_data)(void*))
+init_objdata_htab(int size, void (*free_data) (void *))
{
hash_init(&htab_objdata, size, 4, free_data);
hashinit(&htab_objdata_keys, 8, 32);
notify(player, T("CHAT: I don't know which channel you mean.")); \
list_partial_matches(player, name, PMATCH_ALL); \
return; \
+ case CMATCH_EXACT: \
+ case CMATCH_PARTIAL: \
default: \
break; \
} \
}
}
+/* 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)
hashadd(name, (void *) func, &htab_function);
}
-static void delete_function(void*);
+static void delete_function(void *);
/** Initialize the function hash table.
*/
{
size_t table_index, i;
FUN *fp = data;
-
+
table_index = fp->where.offset;
mush_free((void *) fp->name, "func_hash.name");
mush_free(fp, "func_hash.FUN");
}
}
+
/** Restore an overridden built-in function.
* \verbatim
* If a built-in function is deleted with @function/delete, it can be
if (!fetch_ufun_attrib(args[0], executor, &ufun, 1))
return;
- first = 0;
+ first = 1;
while (1) {
words = 0;
for (n = 0; n < lists; n++) {
static void do_new_spitfile(dbref player, char *arg1, help_file *help_dat);
static const char *string_spitfile(help_file *help_dat, char *arg1);
static help_indx *help_find_entry(help_file *help_dat, const char *the_topic);
-static char *list_matching_entries(char *pattern, help_file *help_dat,
- const char *sep);
+static const char *list_matching_entries(char *pattern, help_file *help_dat,
+ const char *sep);
static const char *normalize_entry(help_file *help_dat, char *arg1);
static void help_build_index(help_file *h, int restricted);
}
/** Return a string with all help entries that match a pattern */
-static char *
+static const char *
list_matching_entries(char *pattern, help_file *help_dat, const char *sep)
{
static char buff[BUFFER_LEN];
* \param data_size size of an individual datum to store in the table.
*/
void
-hash_init(HASHTAB *htab, int size, int data_size, void (*free_data)(void*))
+hash_init(HASHTAB *htab, int size, int data_size, void (*free_data) (void *))
{
int i;
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
extern char escaped_chars[UCHAR_MAX + 1];
+static void
+insert_spaces(int count, int dospace, char *buff, char **bp)
+{
+ if (count) {
+ if (count >= 5) {
+ safe_str("[space(", buff, bp);
+ safe_number(count, buff, bp);
+ safe_str(")]", buff, bp);
+ } else if (count == 1) {
+ if (dospace) {
+ safe_str("%b", buff, bp);
+ } else {
+ safe_chr(' ', buff, bp);
+ }
+ } else {
+ /* Take care of the final %b */
+ count--;
+ if (dospace) {
+ safe_str("%b", buff, bp);
+ count--;
+ }
+ while (count) {
+ safe_chr(' ', buff, bp);
+ count--;
+ if (count) {
+ count--;
+ safe_str("%b", buff, bp);
+ }
+ }
+ safe_str("%b", buff, bp);
+ }
+ }
+}
+
char *
decompose_str(char *what)
{
char ansi_letter = '\0';
int len;
int dospace;
+ int spaces;
int flag_depth, ansi_depth;
int digits;
safe_chr('\\', value, &s);
}
#endif
+
dospace = 1;
+ spaces = 0;
for (; *ptr; ptr++) {
switch (*ptr) {
case ' ':
- if (dospace) {
- safe_str("%b", value, &s);
- } else {
- safe_chr(' ', value, &s);
- }
- dospace = !dospace;
+ spaces++;
break;
case '\n':
+ insert_spaces(spaces, dospace, value, &s);
+ spaces = 0;
dospace = 0;
safe_str("%r", value, &s);
break;
case '\t':
+ insert_spaces(spaces, dospace, value, &s);
+ spaces = 0;
dospace = 0;
safe_str("%t", value, &s);
break;
case ESC_CHAR:
+ insert_spaces(spaces, dospace, value, &s);
+ spaces = 0;
ptr++;
if (!*ptr) {
ptr--;
} 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;
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 || !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') {
}
break;
default:
+ insert_spaces(spaces, dospace, value, &s);
+ spaces = 0;
if (escaped_chars[(unsigned int) *ptr]) {
safe_chr('\\', value, &s);
}
}
}
/* Now check the last space. */
- if (*(s - 1) == ' ') {
- s -= 1;
- safe_str("%b", value, &s);
- }
+ insert_spaces(spaces, dospace, value, &s);
+ spaces = 0;
for (; ansi_depth > 0; ansi_depth--) {
safe_str(")]", value, &s);
}
static int hft_initialized = 0;
static void init_hft(void);
-static void delete_dbref(void*);
+static void delete_dbref(void *);
/** Free a player_dbref struct. */
static void
-delete_dbref(void *data)
+delete_dbref(void *data)
{
mush_free(data, "plyrlist.entry");
}
{
if (hft_initialized)
hashflush(&htab_player_list, 256);
- else
+ else
init_hft();
}
sigfillset(&mask);
sigprocmask(SIG_BLOCK, &mask, NULL);
#elif defined(WIN32)
- /* The only signals Windows knows about */
+ /* The only signals Windows knows about */
signal(SIGABRT, SIG_IGN);
signal(SIGFPE, SIG_IGN);
signal(SIGILL, SIG_IGN);
/** Either an order comparison or a wildcard match with no memory.
*
- * This routine will cause crashes if fed NULLs instead of strings.
*
* \param s pattern to match against.
* \param d string to check.
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);
- }
-
- return quick_wild_new(s, d, cs);
+ 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);
+ default:
+ return quick_wild_new(s, d, cs);
+ }
+ } else
+ return 0;
}
/** Does a string contain a wildcard character (* or ?)?
mv -f ../hdrs/temp.$$.h ../hdrs/cmds.h
fi
-if [ -d "../win32" ]; then
- cp ../hdrs/cmds.h ../win32/cmds.h
-fi
-
;;
functions)
else
mv -f ../hdrs/temp.$$.h ../hdrs/funs.h
fi
-
-if [ -d "../win32" ]; then
- cp ../hdrs/funs.h ../win32/funs.h
-fi
;;
esac
!NO!SUBS!
-How to compile PennMUSH 1.7.x under Windows (MSVC++/MS VS.NET)\r
+How to compile PennMUSH 1.8.x under Windows (MSVC++/MS VS.NET)\r
----------------------------------------------\r
by Nick Gammon <nick@gammon.com.au> and Javelin and Luuk de Waard\r
+Updated by Ervin Hearn <ehearn@pennmush.org>\r
\r
-Last update: Monday, 1 November 2002\r
+Last update: Saturday, 11 November 2006\r
\r
1. From the top-level pennmush directory,\r
- Copy the following files to:\r
-\r
- win32/config.h config.h\r
- win32/confmagic.h confmagic.h\r
- win32/options.h options.h\r
- win32/cmds.h hdrs/cmds.h\r
- win32/funs.h hdrs/funs.h\r
- win32/patches.h hdrs/patches.h\r
- src/local.dst src/local.c\r
- src/funlocal.dst src/funlocal.c\r
- src/cmdlocal.dst src/cmdlocal.c\r
- src/flaglocal.dst src/flaglocal.c\r
- game/mushcnf.dst game/mush.cnf\r
-\r
- Project files for MSVC++:\r
- win32/pennmush.dsw pennmush.dsw\r
- win32/pennmush.dsp pennmush.dsp\r
-\r
- Project files for MS VS.NET:\r
- win32/pennmush.vcproj pennmush.vcproj\r
- win32/pennmush.sln pennmush.sln\r
-\r
- (If you've already got src/*local.c files that you've modified,\r
- you'll just have to make sure that there are no new functions\r
- in src/*local.dst that're missing in your src/*local.c files)\r
+ Copy the following files to:\r
+\r
+ For MSVC++ 6:\r
+ win32/msvc6/pennmush.dsw pennmush.dsw\r
+ win32/msvc6/pennmush.dsp pennmush.dsp\r
+ win32/config.h config.h\r
+ win32/confmagic.h confmagic.h\r
+ win32/options.h options.h\r
+ win32/cmds.h hdrs/cmds.h\r
+ win32/funs.h hdrs/funs.h\r
+ win32/patches.h hdrs/patches.h\r
+ src/cmdlocal.dst src/cmdlocal.c\r
+ src/flaglocal.dst src/flaglocal.c\r
+ src/funlocal.dst src/funlocal.c\r
+ src/local.dst src/local.c\r
+ game/mushcnf.dst game/mush.cnf\r
+ game/aliascnf.dst game/alias.cnf\r
+ game/namescnf.dst game/names.cnf\r
+ game/restrictcnf.dst game/restrict.cnf\r
+\r
+\r
+ For MS VS.NET:\r
+ win32/msvc.net/pennmush.vcproj pennmush.vcproj\r
+ win32/msvc.net/pennmush.sln pennmush.sln\r
+\r
+ VS.NET has been configured to copy the .dst files automatically if they\r
+ do not exist, and the header files each time the project is compiled. This\r
+ can be disabled or changed by going to Project -> pennmush Properties ->\r
+ Configuration Properties -> Build Events -> Pre-Build Event and Post-Build\r
+ Event.\r
+\r
+\r
+ If you've already got src/*local.c files that you've modified,\r
+ you'll just have to make sure that there are no new functions\r
+ in src/*local.dst that are missing in your src/*local.c files\r
\r
2. If you're running under Windows NT, you may wish to edit options.h\r
and uncomment the #define NT_TCP option. If you can build\r
\r
5. From the top-level pennmush directory, the binary is: game/pennmush.exe\r
\r
+*** Note: Windows defaults to a stack size of 1 MB. The supplied project files\r
+set the stack size to 8MB to match the default environment on Linux systems and\r
+resolve several issues of early code termination on Windows. This setting can\r
+also be changed on the precompiled executable by using the 'editbin.exe' tool\r
+supplied by Microsoft in the Visual Studio installation, including the free\r
+Express version. To set the stack size (in KB) run the following from a\r
+command prompt in the game directory: editbin /STACK:<size> pennmush.exe\r