mirror of
git://git.psyced.org/git/psyclpc
synced 2024-08-15 03:20:16 +00:00
initial git creation
This commit is contained in:
commit
2ede0de60e
278 changed files with 230984 additions and 0 deletions
.gitignoreANNOUNCECHANGELOGCOPYING.LIBCOPYRIGHTCREDITSFAQHELPINSTALLREADMETODO
etc
mudlib
ACCESS.ALLOWREADMEastar.cdhrystone.cdhrystone2.cdns_resolve.cerq-tool.cmaster_skeleton.cpgsql.cpsyc-tls.cquery_ip_name.csimul_efun-dr.c
psyclpc.1sys
comm.hcommands.hdebug_info.hdebug_message.hdriver_hook.herq.hfiles.hfunctionlist.hidn.hinclude_list.hinherit_list.hinput_to.hlpctypes.hobjectinfo.hpgsql.hregexp.hrtlimits.hsent.hstrings.hstruct_info.htelnet.htime.htls.htrace.hwizlist.h
telnetneg.ctelnetneg.htest_master.cuni-crasher
src
C_COMPILER_BUGSMakefile.inaccess_check.caccess_check.hactions.cactions.halloca.carray.carray.hauthlocal.cauthlocal.h
autoconf
backend.cbackend.hbitstrings.cbitstrings.hbytecode.hcall_out.ccall_out.hclosure.cclosure.hcomm.ccomm.hconfig.h.inconfigurecontrib
empty-mapping-check-fix.patchfind_object.patchget_eval_number.patchimprove-statistics.patchload_object.patchzesstra-foreach.patch
driver.hdumpstat.cdumpstat.h
19
.gitignore
vendored
Normal file
19
.gitignore
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
CVS
|
||||
.config
|
||||
~$*
|
||||
.DS_Store
|
||||
.metadata
|
||||
.actionScriptProperties
|
||||
.#*
|
||||
world/net/place/_*.c
|
||||
world/net/include/place.i
|
||||
*~
|
||||
*.swf
|
||||
*.swp
|
||||
*.rej
|
||||
*.log
|
||||
*.pem
|
||||
*old
|
||||
*bak
|
||||
*diff
|
||||
*orig
|
73
ANNOUNCE
Normal file
73
ANNOUNCE
Normal file
|
@ -0,0 +1,73 @@
|
|||
CODE RELEASE: [lpmud driver] psyclpc 4.0.6 - derivate of LDMud
|
||||
|
||||
ladies & gentlemen,
|
||||
|
||||
wanted to inform you in accordance with Lars we have started shipping
|
||||
our own LDMUD distribution as it was getting just too complicated to
|
||||
maintain all necessary patches in our installation procedure for the
|
||||
psyced server (multi-protocol chat/messaging server).
|
||||
|
||||
wrapping up our own tars has simplified distributing psyced a lot.
|
||||
we also dared to change the name (1) to make it less confusing for
|
||||
our users that "ldmud" belongs to "psyced" and (2) not to have to
|
||||
fulfil the high expectations you would put into an LDMud product. ;)
|
||||
|
||||
psyclpc is a derivate of ldmud 3.3.714 (the current version in the
|
||||
ldmud repository since over a year) with the following changes:
|
||||
|
||||
1. The driver has been modularized in such a way that you can turn
|
||||
each function, many of them typically needed for MUD use, on or
|
||||
off. The optional modules are:
|
||||
|
||||
* actions (MUD command parser)
|
||||
* built-in editor 'ed'
|
||||
* inventories, environments and light
|
||||
* paranoid reference checks
|
||||
* shadowing
|
||||
* socket snooping
|
||||
* swapping
|
||||
|
||||
Turning any of these off makes your driver lighter and faster,
|
||||
which is quite nice. ;)
|
||||
|
||||
2. New optional packages have been added:
|
||||
|
||||
* expat XML parser
|
||||
* DNS SRV resolution
|
||||
* JSON parser
|
||||
* automatic localhost telnet authentication via /proc.
|
||||
|
||||
3. TLS support has been improved a lot.
|
||||
|
||||
4. Minor fixes concerning 64 bit compilation, Solaris compilation,
|
||||
UTF-8 support, outgoing connections and multi-homed connects for
|
||||
dynamic DNS.
|
||||
|
||||
5. Debugging message style has been revamped and the secondary debug
|
||||
log made optional, but you can switch it back to ldmud compatible
|
||||
whenever you want.
|
||||
|
||||
6. All new functions are neatly configurable using the settings files
|
||||
introduced by LDMud.
|
||||
|
||||
all in all no big deal, but it is being run in various places and
|
||||
seems to perform flawlessly, so that in itself is nice (the bugfixes
|
||||
submitted on mantis are really good!).
|
||||
|
||||
we didn't remove anything of the MUD support, just made it all optional
|
||||
and configurable, so you can still run an LPMud on this. there is even a
|
||||
new field in the configure.in letting you put the "ldmud" name back in
|
||||
place, or whatever you want your driver to call itself. :)
|
||||
|
||||
by the way, you may be interested that the psyced's "mudlib" is architected
|
||||
in a way that you can merge it into an existing mud. this brings PSYC, XMPP,
|
||||
IRC, RSS and several other features into your system - there has even been
|
||||
an experimental adaption of intermud over PSYC.. sort of an intermud 4.
|
||||
|
||||
here are all the links:
|
||||
psyclpc http://lpc.psyc.eu
|
||||
psyced http://www.psyced.org
|
||||
psyc http://about.psyc.eu
|
||||
|
||||
questions? telnet psyced.org
|
||||
|
116
CHANGELOG
Normal file
116
CHANGELOG
Normal file
|
@ -0,0 +1,116 @@
|
|||
2008-05-28 (fippo/lynX) (4.0.8)
|
||||
+ new efuns:
|
||||
string strftime(string, int default: F_TIME);
|
||||
int strptime(string, string);
|
||||
+ temporary efun tls_want_peer_certificate()
|
||||
- SSL_set_shutdown() hopefully fixes openssl crasher on SSL_ERROR_SYSCALL
|
||||
|
||||
2008-01-21 (fippo) (4.0.7)
|
||||
+ new enable_binary() efun to allow for binary networking (EXPERIMENTAL)
|
||||
+ new ieee754_to_string(float) and string_to_ieee754(string)
|
||||
efuns to support this specific flavour of floating point notation
|
||||
|
||||
2008-01-12 (fippo)
|
||||
- fixed erq SRV support on 64 bit architectures
|
||||
|
||||
2008-01-02 (lynX)
|
||||
- repaired builtin pcre utf8 support
|
||||
+ use builtin pcre by default until utf8 support becomes more popular
|
||||
in distributions (can be an unnecessary complication otherwise)
|
||||
|
||||
2007-10-07 (Lars)
|
||||
- foreach(int i: <num>) recognizes if <num> is negative
|
||||
and throws an error. (Bug #503, from ldmud)
|
||||
- (configure) When testing for libiconv, reference a real libiconv method.
|
||||
This catches situations where libiconv exists, but is of the
|
||||
wrong architecture.
|
||||
|
||||
2007-08-29 (lynX) (4.0.6)
|
||||
+ #define USE_RESTORED_OBJECTS in object.c teaches
|
||||
save_object() to store object names using a `name` syntax and
|
||||
restore_object() to put it back in circulation in form of strings.
|
||||
+ enable_use_restored_objects activates this (but we don't use it yet)
|
||||
+ erq now terminates peacefully whenever the driver shuts down
|
||||
- cleaned up a lot of debug output behaviour and put it into
|
||||
#ifdef VERBOSE and #ifdef USE_LDMUD_COMPATIBILITY
|
||||
+ enable_use_debug_log=no sends all debug output to stdout
|
||||
- enable_backtrace_always and enable_ldmud_compatibility
|
||||
replaced by enable_use_ldmud_compatibility
|
||||
- replaced enable_use_paranoid_refs by enable_use_paranoia which now
|
||||
also ifdefs the "strict checks" code
|
||||
+ added enable_use_experimental
|
||||
+ EXPERIMENTAL: send TLSv1 handshake when acting as TLS client
|
||||
|
||||
2007-08-19 (lynX) (4.0.5)
|
||||
+ enable_use_builtin_editor=no disables the built-in text editor 'ed'.
|
||||
+ enable_use_inventories=no removes all MUD-related functionality
|
||||
concerning inventories and environments.
|
||||
+ enable_use_snooping=no disables all socket snooping code.
|
||||
+ enable_use_actions=no disables all MUD-style command parser facilities.
|
||||
+ enable_use_socket_limits=no disables limits on amount of entered lines
|
||||
per second including get/set_max_commands() efuns.
|
||||
+ enable_use_shadowing=no disables various forms of shadowing.
|
||||
+ enable_use_swap=no disables the ability to swap program bytecode to disk.
|
||||
+ enable_use_paranoid_refs=no disables paranoid runtime checks, you only
|
||||
need this if you are making dangerous changes to the driver code
|
||||
or looking for mysterious crashes.
|
||||
+ enable_ldmud_compatibility=no mostly affects unnecessary debug messages
|
||||
which will otherwise appear for maximum compatibility.
|
||||
+ optimized outconn management with num_pending_outconns & extra_jobs_to_do
|
||||
|
||||
2007-08-16 (lynX) (4.0.4)
|
||||
+ added detection of #include <arpa/nameser_compat.h> which seems to
|
||||
determine the availability of DNS SRV extensions
|
||||
- erq will be compiled without SRV instead of failing to compile
|
||||
+ __NO_SRV__ is added to the predefines in lex.c if SRV is unavailable
|
||||
+ enable_backtrace_always=yes stops the stupid behaviour of hiding away
|
||||
backtraces in the debug log (the debug log should only be necessary
|
||||
for driver developers, not lpc coders). It doesn't have to be like php,
|
||||
where the end user sees the full backtrace, but at least the admin should
|
||||
be considered sufficiently competent. :)
|
||||
+ new RE_UTF8 flag mirrors the PCRE_UTF8 flag and allows operating on
|
||||
unicode character ranges using regexps.
|
||||
|
||||
2007-07-06 (lynX) (4.0.3)
|
||||
+ added zippo's 64 bit patches. apparently do not break 32 bit architectures.
|
||||
thx to Casey Zacek; Zippo @ EotL; mud.eotl.org 2010
|
||||
|
||||
2007-05-07 (lynX) (4.0.2)
|
||||
+ moved program name ('psyclpc' formerly 'ldmud') into configure.in
|
||||
|
||||
2007-05-04 (lynX) (4.0.2)
|
||||
- fixed a compilation problem on Solaris derivates
|
||||
+ added authlocal
|
||||
+ added --with_max_net_connects, --with-size_socket_buffer
|
||||
and forced settings when running ./configure without args
|
||||
- applied http://mantis.bearnip.com/view.php?id=472 to fix zero byte
|
||||
output in tell_object(), tell_room() and say()
|
||||
+ fixed multihomed connect to improve dynamic dns support
|
||||
|
||||
2007-05-03 (fippo) (4.0.1)
|
||||
- removed TLS CRL implementation as it isn't being used currently
|
||||
and crashes on some systems
|
||||
|
||||
2007-04-17 (lynX) (4.0.0)
|
||||
+ using new major version number to avoid conflicts with LDMUD.
|
||||
|
||||
2007-04-08 (lynX)
|
||||
- removed doc, mud, src/util/xerq, HISTORY, src/settings.
|
||||
- crippled CHANGELOG.
|
||||
- updated COPYRIGHT and README.
|
||||
+ created new CVS and introduced the pragmatic name 'psyclpc'
|
||||
- some values adjusted to heavy networking use
|
||||
|
||||
2007-02-16 (fippo)
|
||||
- TLS fixed
|
||||
+ support for TLS CRLs
|
||||
+ JSON (javascript object notation) efuns
|
||||
- set_combine_charset allows newline and null to be combined
|
||||
- some minor patches
|
||||
+ pkg-expat
|
||||
|
||||
2006-07-09 (Lars Duening) (3.3.714)
|
||||
- Created snapshot.
|
||||
|
||||
For prior CHANGELOG and HISTORY see the LDMud distribution.
|
||||
|
481
COPYING.LIB
Normal file
481
COPYING.LIB
Normal file
|
@ -0,0 +1,481 @@
|
|||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the library GPL. It is
|
||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Library General Public License, applies to some
|
||||
specially designated Free Software Foundation software, and to any
|
||||
other libraries whose authors decide to use it. You can use it for
|
||||
your libraries, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the library, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link a program with the library, you must provide
|
||||
complete object files to the recipients so that they can relink them
|
||||
with the library, after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
Our method of protecting your rights has two steps: (1) copyright
|
||||
the library, and (2) offer you this license which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
Also, for each distributor's protection, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
library. If the library is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original
|
||||
version, so that any problems introduced by others will not reflect on
|
||||
the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that companies distributing free
|
||||
software will individually obtain patent licenses, thus in effect
|
||||
transforming the program into proprietary software. To prevent this,
|
||||
we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary
|
||||
GNU General Public License, which was designed for utility programs. This
|
||||
license, the GNU Library General Public License, applies to certain
|
||||
designated libraries. This license is quite different from the ordinary
|
||||
one; be sure to read it in full, and don't assume that anything in it is
|
||||
the same as in the ordinary license.
|
||||
|
||||
The reason we have a separate public license for some libraries is that
|
||||
they blur the distinction we usually make between modifying or adding to a
|
||||
program and simply using it. Linking a program with a library, without
|
||||
changing the library, is in some sense simply using the library, and is
|
||||
analogous to running a utility program or application program. However, in
|
||||
a textual and legal sense, the linked executable is a combined work, a
|
||||
derivative of the original library, and the ordinary General Public License
|
||||
treats it as such.
|
||||
|
||||
Because of this blurred distinction, using the ordinary General
|
||||
Public License for libraries did not effectively promote software
|
||||
sharing, because most developers did not use the libraries. We
|
||||
concluded that weaker conditions might promote sharing better.
|
||||
|
||||
However, unrestricted linking of non-free programs would deprive the
|
||||
users of those programs of all benefit from the free status of the
|
||||
libraries themselves. This Library General Public License is intended to
|
||||
permit developers of non-free programs to use free libraries, while
|
||||
preserving your freedom as a user of such programs to change the free
|
||||
libraries that are incorporated in them. (We have not seen how to achieve
|
||||
this as regards changes in header files, but we have achieved it as regards
|
||||
changes in the actual functions of the Library.) The hope is that this
|
||||
will lead to faster development of free libraries.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, while the latter only
|
||||
works together with the library.
|
||||
|
||||
Note that it is possible for a library to be covered by the ordinary
|
||||
General Public License rather than by this special one.
|
||||
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library which
|
||||
contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Library
|
||||
General Public License (also called "this License"). Each licensee is
|
||||
addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also compile or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
c) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
d) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the source code distributed need not include anything that is normally
|
||||
distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Library General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
77
COPYRIGHT
Normal file
77
COPYRIGHT
Normal file
|
@ -0,0 +1,77 @@
|
|||
psyclpc, an LDMud with a couple of patches and optimizations for psyced.
|
||||
Patched by fippo and lynX.
|
||||
Our patches usually also merge into LDMud eventually.
|
||||
|
||||
LDMud, a LPmud gamedriver.
|
||||
Copyright 1997-2006 by Lars Duening.
|
||||
|
||||
LDMud is based on LPmud, which is
|
||||
Copyright 1989-1991 by Lars Pensjö, and, starting with version 3.1.2,
|
||||
Copyright 1991-1997 by Joern Rennecke.
|
||||
|
||||
These copyrights notices are actually incorrect, as each of the many
|
||||
authors below is still owner of his or her copyright. Also, since about
|
||||
1990, LPmud contains GPL code, making the original restrictive licensing
|
||||
scheme invalid. At the same time the COPYLEFT was added, which is now
|
||||
to be considered the only viable licensing scheme for LPmud and its
|
||||
derivates.
|
||||
|
||||
Ever from the start LPMud used the GNU malloc implementation, it
|
||||
was thus never fit to become restricted from GPL-incompliant use.
|
||||
The only code in this driver which originates from the CD driver is
|
||||
the UDP implementation. In 1993 Jacob Hallen <jacob@cd.chalmers.se>
|
||||
writes "The UDP stuff is to be considered public domain."
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
LDMud contains contributions of many volunteers as listed in the file CREDITS.
|
||||
Of these, the following packages are subject of their own copyright when
|
||||
used outside the context of this gamedriver; please refer to the appropriate
|
||||
files for details.
|
||||
|
||||
The regexp package is based on the code written by Henry Spencer.
|
||||
|
||||
The portable crypt() implementation is Copyright by Eric Young.
|
||||
|
||||
The smalloc allocator was written by Sean T. Barrett and put into the
|
||||
public domain.
|
||||
|
||||
The 'ed' editor (with the exception of the indentation code) is Copyright
|
||||
by Brian Beattie, Kees Bot and others.
|
||||
|
||||
The non-corrupting indentation code for the 'ed' editor was written and
|
||||
contributed by Felix A. Croes (<felix@dworkin.nl>) from his DGD gamedriver.
|
||||
|
||||
The sprintf() efun was written by Sean A. Reith and put into the public
|
||||
domain.
|
||||
|
||||
All code taken from the MudOS driver is Copyright by Tim Hollebeek and
|
||||
the original authors. Use for other purposes than LPmud drivers or under
|
||||
licenses significantly different from the original LPmud license needs
|
||||
explicite permission.
|
||||
|
||||
The random() efun is implemented using the Mersenne Twister generator which is
|
||||
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, and subject
|
||||
to a BSD-style license. The implementation is the faster implementation based
|
||||
on Shawn Cokus and Matthew Belle's improvements. See random.c for the full
|
||||
text of the license.
|
||||
|
||||
The MD5 message digest algorithm is Copyright (C) 1991-2, RSA Data Security,
|
||||
Inc.
|
||||
|
||||
The Apache-compatible MD5 password encryption is Copyright (C) 2000 Apache
|
||||
Software Foundation.
|
||||
|
||||
The PCRE (Perl Compatible Regular Expression) is Copyright (C) 1997-2001 by
|
||||
Philip Hazel. LDMud contains just the files required for the driver (with
|
||||
small modifications); see pcre/LICENCE for the licence terms and the location
|
||||
of the full package, and pcre/README.LDMUD for an explanation of the changes.
|
||||
|
||||
The lpc-mode.el for EMACS is Copyright (C) 2002 Vivek Dasmohapatra
|
||||
<vivek@etla.org>, and distributed under the GPL.
|
||||
|
||||
The PostgreSQL package is based on code written and donated 2001 by Florian
|
||||
Heinz.
|
||||
|
||||
The MCCP implementation was originally written for Finalfrontier by
|
||||
Bastian Hoyer.
|
281
CREDITS
Normal file
281
CREDITS
Normal file
|
@ -0,0 +1,281 @@
|
|||
The program was originally written by
|
||||
|
||||
Lars Pensj|, April 1989 (lars@cd.chalmers.se (no longer valid)).
|
||||
|
||||
Lars gives the following credit:
|
||||
|
||||
The regexp package was made by Henry Spencer.
|
||||
|
||||
The ed package was not done by me. See the file ed.c for information.
|
||||
|
||||
Bit manipulations was implemented by pell@lysator.liu.se who also found
|
||||
several bugs that had eluded me for months.
|
||||
|
||||
Valuable help and hints from: Mark Nagel, James Seidman, Moonchilde and more.
|
||||
|
||||
Roland Dunkerley III fixed for-loops, do-while and the operators ++ and --.
|
||||
|
||||
Sean T Barrett made smalloc.c.
|
||||
|
||||
Lennart Augustsson convinced me to implement a compiler for a virtual
|
||||
stack machine. He also implemented the built-in preprocessor.
|
||||
|
||||
John S. Price found and fixed many bugs.
|
||||
|
||||
The shadow idea was "forwarded" to me by John S. Price from Team Cthulhu
|
||||
(Bill Burdick, Roy Riggs, Mitch Adler).
|
||||
|
||||
Michael Malone, Michael O'Reilly, Klaus Rennecke, J|rn Rennecke and
|
||||
Germano Caronni found and fixed a large amount of bugs.
|
||||
|
||||
Petri Wessman fixed changes for SCO unix and AIX.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Joern Rennecke ( amylaar@cs.tu-berlin.de ) gives this credit:
|
||||
|
||||
The non-corrupting indentation code for ed was written by Felix A. Croes,
|
||||
aka Dworkin (<felix@dworkin.nl>) and originates from his DGD.
|
||||
|
||||
Mud-sprintf() is from Lynscar (Sean A Reith, <gusar@uniwa.oz.au> and
|
||||
was donated into the Public Domain.
|
||||
|
||||
The alist based mapping implementation was supplied by Dworkin.
|
||||
|
||||
The idea for query_actions and an implementation that has been partially used
|
||||
is from Peter Eriksson (aka lpd) pen@lysator.liu.se
|
||||
|
||||
The port to Amiga was done by Mateese ( Lars Duening )
|
||||
|
||||
The udp connectivity is from the CD driver, and was fitted in by deepthought.
|
||||
|
||||
Demos, Freaky, Hurl, Hyp, Mateese, Pepel and Jof did a lot of alpha
|
||||
testing.
|
||||
|
||||
Reimer Behrends located a lot of bugs. He also supplied a portable macro to
|
||||
test numbers for having but a single bit set, a mergesort based
|
||||
sort_array() and variadic function support.
|
||||
|
||||
get_object_actions() was supplied by herp.
|
||||
|
||||
Marcus Meissner found and fixed many bugs.
|
||||
|
||||
Carl White, Mark (ec179@city.ac.uk), Archimedes (Robert Fuller), Eric Blade,
|
||||
Mitchell Brandsma, Sam Bobroff, Jim Cogbill, Ben Fennema,
|
||||
Sorva (Ed Zielinski), Loke@Wonderland (Solem), Claus S. Jensen, Nils Magnus,
|
||||
samo@MorgenGrauen, Frobozz (Bryan Schuler), Sique@Nightfall, APJ,
|
||||
Deathknight, Tero Jyri Michael Pelander (tpeland@utu.fi),
|
||||
Willem van der Oord (willem@marble.dcr.net), Hate@MorgenGrauen,
|
||||
Bob Farmer, Randor@EoP, Trevor Phillips, Robert M. Zigweid, Inspiral,
|
||||
Brian Gerst, Rasmus H. Hansen, Demodian (John Kurtz), William J. Burton,
|
||||
Patrick Li, Niilo Paasivirta, Frank Stolze, Penelope@Avalon,
|
||||
Nathan@Unholy Lands, mubo@SiliconDream, Sunblood@Tubmud, Alfe@Tubmud,
|
||||
Tatu Saloranta, Chameloid@Tubmud and Martin Brenner (deepthought) reported bugs.
|
||||
|
||||
Foslay did the OS/2 port.
|
||||
|
||||
Ray Gilbert originally did the MSDOS port, which was modified later by
|
||||
Rasmus Hellbug Hansen.
|
||||
|
||||
Marcus Meissner contributed regreplace().
|
||||
|
||||
Slider@Tubmud supplied GnuWin32 patches.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Lars Duening thanks:
|
||||
|
||||
- Dana Durkee and the magnificient Wessex for enhancing my life.
|
||||
- the citizens of One Step Beyond, PK-Mud and UNItopia for enduring my
|
||||
driver experiments.
|
||||
- Malcom Tester (malcom.tester@comcast.net) for providing me with access to
|
||||
a Solaris system for testing.
|
||||
- Elric (elric@lpmud.com) for providing me with access to
|
||||
a FreeBSD system for testing.
|
||||
- Blackcat (?) for providing me with access to a Linux system for testing.
|
||||
- Freaky for providing me with access to an Irix system for testing, numerous
|
||||
bug reports, and lots of patience when new versions crashed even faster
|
||||
than the old ones.
|
||||
- Kees Leune for providing me with access to a Linux/Sparc system for
|
||||
testing.
|
||||
- Stefan Petri and contributors for the extensive documentation of the
|
||||
Amylaar driver (see also doc/README).
|
||||
- the MudOS programmers for the efun terminal_colour() and Michael Schaefer
|
||||
for adapting it for LDMud.
|
||||
- Martin Brenner: initial multi-port implementation, inetd compatibility
|
||||
code.
|
||||
- Brian Gerst (bgerst@quark.vpplus.com) for the xerq daemon.
|
||||
- Reinhard Pfau (Reinhard.Pfau@unix-ag.org, Mubo@SiliconDream) brought
|
||||
the autoconf mechanism up to date.
|
||||
- Ron Koerner (ron.koerner@gmx.de, Righ@FinalFrontier) provided the
|
||||
initial implementation of inline closures modelled after MudOS' syntax.
|
||||
- Uwe (uwe@6bone.informatik.uni-leipzig.de) provided the basic IPv6 support.
|
||||
- Mark Daniel Reidel (Karm@Nightfall) did the first implementation of
|
||||
the mySQL efuns.
|
||||
- Dennis VanHoey (devanhoe@usol.com) did the compiling and testing for the
|
||||
Darwin port.
|
||||
- Bart van Driessche (bart@multi.franken.de, Hunter@FinalFrontier) did the
|
||||
new OS/2 port.
|
||||
- Menaures added the tab character conversion to the editor, and gleefully
|
||||
found new ways to crash the driver.
|
||||
- Adam Helps donated the LPC implementation of the A* pathfinding algorithm.
|
||||
- Christian Welzel adapted ptmalloc (a threadsafe variant of Doug Lea's
|
||||
allocator) for LDMud and extended it to support garbage collection.
|
||||
- for bug reports, critics, fixes, patches and other support:
|
||||
Adam Helps (ahelps@cs.byu.edu, acius@simud.org)
|
||||
Alex@TubMud (at16@st-andrews.ac.uk)
|
||||
Alexander Fetke (alfebtcd@cs.tu-berlin.de, Alfe@Tubmud)
|
||||
Alexander Dobrinescu (ad@artifacts.de, Lev@FinalFrontier)
|
||||
Anders Strandloev Elkjaer (ase@cs.auc.dk)
|
||||
Andre Meiske (guandalug@magellan.tat.physik.uni-tuebingen.de)
|
||||
Andreas Grammlich (andreas.grammlich@prepress.de, Gum@Wunderland)
|
||||
Andre Grosse (ag17@irz.inf.tu-dresden.de, Patryn@Morgengrauen)
|
||||
Andreas Fischer (andreas.fischer@physik.tu-chemnitz.de)
|
||||
Andreas Klauer (menaures@metamorpher.de, Menaures@Unitopia)
|
||||
Andreas Weller (aw6@informatik.uni-ulm.de, Zwirch@Carledon)
|
||||
Andres Cvitkovich (ac@twig.mond.at, ac@zwerg.at, Woody@Silberland)
|
||||
Andrew Weisz (elarke01@snet.net)
|
||||
Andy Zeneski (jaz@zsolv.com)
|
||||
Arne @ Elridion
|
||||
Athanasia Steele (azurite@mail1.nai.net)
|
||||
Baba@Avalon
|
||||
Bastian Hoyer (hoyer@wisc.de, dafire@dafire.de)
|
||||
Ben Fennema (bfennema@ix.netcom.com)
|
||||
Bertram Felgenhauer (bf3@irz.inf.uni-dresden.de, Fuchur@Wunderland)
|
||||
Bill Andrulonis (bill.andrulonis@citrix.com, Bofin@Realmsmud)
|
||||
Billy Pembroke (wpem@comcast.net)
|
||||
Blackcat@PK-Mud (amuelle1@htwm.de)
|
||||
Brandon (pothole@darkspyre.quad.net)
|
||||
Brandon Mathis (brandon.mathis@medsolutions.com)
|
||||
Bruce Mitchell (mitchell@manly.delconet.com, Klahn@Manly Mud)
|
||||
Carlo v. Loesch (psyc://psyced.org/~lynX)
|
||||
Carsten Pluntke (su0289@studserver.uni-dortmund.de, Vejar@ForgottenDreams)
|
||||
Casey Zacek (cz@netspire.net, zippo@eotl)
|
||||
Chris Bender (chris.bender@attbi.com)
|
||||
Christian "Leonidas" Becker (cbecker@informatik.hu-berlin.de)
|
||||
Christian Fiedler (fido2@gmx.net)
|
||||
Christian Kirschbaum (chrissy@cs.tu-berlin.de, Chameloid@Tubmud)
|
||||
Christian Mudra (c_mudra@informatik.uni-kl.de, Coogan@Tubmud)
|
||||
Christian Welzel (gawain@wh9.tu-dresden.de, Sir_Gawain@camlann.de,
|
||||
Gawain@Regenbogen)
|
||||
Craig Venz (Craig Venz@citrix.com, Kilan@Realmsmud)
|
||||
croft@UNItopia.rus.uni-stuttgart.de
|
||||
Collin Baillie (sanac@optushome.com.au)
|
||||
Dale "Elric" Perkins (dale_perkins@mac.com, dale@lpmud.com)
|
||||
Daniel von Dincklage (daniel@ozet.de, Sunblade@SiliconDream),
|
||||
Daniel Fischer (dfischer@gmx.de, Dan@Gueldenland)
|
||||
Daniel Sloan (sloand@alphalink.com.au)
|
||||
Daryth Kendrickson (stavros@deadofnight.com)
|
||||
David Gibbs (ishara@btinternet.com)
|
||||
David 'Greyelk' Gibby (oop_apprentice@yahoo.com)
|
||||
Dennis VanHoey (dvanhoe@usol.com)
|
||||
Derek Baron (dbaron_ks@hotmail.com)
|
||||
Dominik Zanettin (zhan@opossum.htu.tuwien.ac.at, Zhan@Beutelland)
|
||||
Edward S. Marshall (esm@logic.net)
|
||||
Enrico Bauermeister (ebauermeister@t-online.de, Enrico@FinalFrontier)
|
||||
Eivind (ekj@ekj.vestdata.no)
|
||||
Erik Meusel (emeusel@prinz-atm.CS.Uni-Magdeburg.De)
|
||||
Fantom (Fantom@Tharsis-Gate.org)
|
||||
Fini Jastrow (Fiona@Wunderland, ujastrow@mail.desy.de)
|
||||
Florian Heinz (ctx@amail.dereference.de)
|
||||
Frank Kirschner (freaky@unitopia.uni-stuttgart.de)
|
||||
Frank Stolze (fstolze@iName.com)
|
||||
Frank Syse (syseworks@mac.com)
|
||||
Gerhard Schmidt (estartu@augusta.de)
|
||||
Gimli@Unitopa (gimli@schlumpf.net)
|
||||
"Gnomi" (gnomi@UNItopia.rus.uni-stuttgart.de)
|
||||
Gunnar Kreitz (gunnark@chello.se)
|
||||
Heiko Kopp (hkopp@informatik.uni-rostock.de, bardioc@bardioc.com,
|
||||
Bardioc@Evermore)
|
||||
Henk Stokhorst (Tha@wxs.nl)
|
||||
Holger Kremss (jur94ewp@studserv.uni-leipzig.de, Holger@web.de,
|
||||
Holger@Wunderland)
|
||||
Jaroslaw Sitek (aron@bobas.nowytarg.pl)
|
||||
Jason Hitt (jhitt25@swbell.net)
|
||||
Jean-Stephane Jokeit (jokeit@gmx.de, xtian@avalon)
|
||||
Joern Rennecke (amylaar@cygnus.co.uk)
|
||||
Jose Manuel Roman (roman@wol.es, Theuzifan uzi@simauria.upv.es)
|
||||
Joseph Graham (randalar@earthlink.net)
|
||||
Josh Rollyson (jrollyson@sosdg.org)
|
||||
Juergen Weickert (Sissi@UNItopia)
|
||||
Karl N. Matthias (karmat@matthias.org)
|
||||
Kathrin Paschen (paschen@ira.uka.de)
|
||||
Kees Leune (c.j.leune@kub.nl)
|
||||
Kent Chilson (kentiepoo@hotmail.com)
|
||||
Kirnan@Avalon
|
||||
Krystal-Anne Rubenstein (punkette@hotmail.com)
|
||||
Kirnan@Avalon
|
||||
Largo@Wunderland (emeusel@csmd.cs.uni-magdeburg.de)
|
||||
Lasse Fuglsang Pedersen (volmer@qeep.dk, Zordiac@DeeperTrouble2)
|
||||
Lee Salzman (lee.salzman@lvdi.net)
|
||||
Logic (logic@logic.net)
|
||||
"Mammi" (mammi@unitopia.uni-stuttgart.de)
|
||||
Manu Mäki (mtmaki@pultti.turkuai.fi, Cendor@Winterkill)
|
||||
Mark Daniel Reidel (Karm@Nightfall,
|
||||
reidelm@rbg.informatik.tu-darmstadt.de)
|
||||
Markus Peter (warp@spin.de, warp@hip.spin.de)
|
||||
Martin (mandragon@morgengrauen)
|
||||
Mat@Maethos
|
||||
Mats Carlberg (matca@lysator.liu.se)
|
||||
Matthew Julius (julius.2@wright.edu)
|
||||
Michael Fedrowitz (mfedrowi@ix.urz.uni-heidelberg.de,
|
||||
Michael_Fedrowiz@gmx.net, Rhodry@ForgottenDreams)
|
||||
Michael Sporn (sporn@mathematik.hu-berlin.de, sunblood@tubmud)
|
||||
Mike Conley (mpc@sgi.net, Tamarindo@Sovereign)
|
||||
mudder@Furtual.ORG
|
||||
"Nathan@Unholy Lands" (mud@pc181.iaee.tuwien.ac.at)
|
||||
Neil McBride (neil@castinian.org)
|
||||
Nepomuck@UNItopia
|
||||
Nick Derewianka (nickd@e-media.com.au)
|
||||
Nico Ehemann (n.ehemann@wzl.rwth-aachen.de)
|
||||
Niels Boehm (bohmmrwc@minet.uni-jena.de, Mariko@Regenbogen)
|
||||
Nuutti Kotivuori (naked@iki.fi)
|
||||
Oskar Linde (d98-oli@nada.kth.se)
|
||||
Parsec
|
||||
Patrick May (patrick.may@cedelgroup.com)
|
||||
Paul Apgar (tiresius@usa.net, tiresius@Cosmos)
|
||||
Philipp Hancke (psyc://goodadvice.pages.de/~fippo)
|
||||
Rainer Doerntge (rainer.doerntge@dlh.de)
|
||||
Rajko Albrecht (ral@alwins-word.de, Alwin@Avalon)
|
||||
Ralph (ralphi@vkr.k-net.dk)
|
||||
Ralph Zitz (RZ@zitz.dk, Nostradamus@OSB)
|
||||
Reimer Behrends (Macbeth@Tubmud)
|
||||
Reinhard Pfau (reinhard@netlab1.hrz.uni-siegen.de, mubo@SiliconDream),
|
||||
Reinhard Vicinus (vicinus@rhrk.uni-kl.de, Risky@Unitopia)
|
||||
"Remsgost" (remsgost@blitzstrahl, radm@remsnet.de)
|
||||
Robb Townsend (meecham@infonline.net)
|
||||
Robert Forshaw (postmaster@rbf.org.uk)
|
||||
Robert Reither (mud@klein.htu.tuwien.ac.at, Nathan@Unholy.Lands)
|
||||
Robert Treml (robert@des.glaubst.net)
|
||||
Rodney Quaye (sark@oberon.krans.com)
|
||||
Ron Dawson (rondawson@syd.eastlink.ca, rdawson@cgc.ns.ca, Caper@PixieMud)
|
||||
Sebastian Huss (huss@informatik.hu-berlin.de, baba@avalon)
|
||||
Shinarae Lluminus@Batmud (shinarae_lluminus@hotmail.com)
|
||||
Slava "DieHARD" Ignatjev (root@impar.com, slava@intersfera.lt)
|
||||
Sieni (sampsa@netsonic.fi)
|
||||
Simon Fischer (firebat@redcrown.de)
|
||||
Stefan Budweiser (Stefan.Budweiser@compaq.com)
|
||||
Stefan Riemer (stefan.riemer@bauing.uni-weimar.de, Peng@FinalFrontier)
|
||||
Stephan Lichtenhagen (lichti@amethyst.chemie.uni-dortmund.de,
|
||||
stephan@lichtenhagen.de, Tiamak@Morgengrauen)
|
||||
Steve Goucher (su2996@eclipse.co.uk)
|
||||
Steve Willoughby (steve@alchemy.com, Ragnarok)
|
||||
Tatu P. Saloranta (doomdark@cc.hut.fi)
|
||||
Terry Penn (terry@simaril.net)
|
||||
TheFinn (thefinn@ar.com.au)
|
||||
Thomas Feldmeier (tfeldmei@student.informatik.uni-ulm.de, Zora@Carledon,
|
||||
zora@alpha.universalware.de)
|
||||
Thorsten Klose (Thorsten.Klose@infineon.com, Avatar@avalon)
|
||||
Tiberian@Unitopia
|
||||
Tmm@UNItopia? (Tmm@gmx.de)
|
||||
Tobias Josefowitz (tobij@goodadvice.pages.de)
|
||||
Tomas (Vandergnome@aol.com)
|
||||
Tomi Valkeinen (tomi.valkeinen@taikatech.com, Tomba@Batmud)
|
||||
Tucita@UNItopia
|
||||
Urv (urv@hispeed.ch)
|
||||
Volker Behr (Sorcerer@AbendDaemmerung, vrbehr@cip.physik.uni-wuerzburg.de)
|
||||
Wayne Woods (w.woods@optusnet.com.au)
|
||||
Willem van der Oort (willem@dcr.net)
|
||||
Wolf Dieter Dallinger (Pulami@Unitopia, wolf.dieter@dallinger.de)
|
||||
Zonk@FinalFrontier (zonk@finalfrontier.mud.de, rueschi@berit-broese.de)
|
||||
The Wizards of Evermore
|
22
FAQ
Normal file
22
FAQ
Normal file
|
@ -0,0 +1,22 @@
|
|||
===============================================================================
|
||||
Why our own derivate of the LDMud?
|
||||
|
||||
* Expecting our psyced admins to find a suitable version made installation
|
||||
unnecessarily complicated, and every now and then an ldmud release does
|
||||
indeed not work for psyced.
|
||||
* We love the work mateese has been doing and still does, and we will
|
||||
surely continue to share all gotchas and improvements so that both
|
||||
variants of LDMud strive. Only we catch ourselves needing to have a
|
||||
shorter change inclusion and release cycle. We asked mateese before
|
||||
taking this step.
|
||||
* For that reason we had been making the psyced install procedure too
|
||||
complicated, as it was always trying to patch some things in the ldmud
|
||||
source, even when it didn't know which ldmud version it was working on.
|
||||
* Now to have psyced and its driver bundled in a pair which is safely known
|
||||
to be happily working together is a simple yet great step forward.
|
||||
* This makes the whole psyced installation base more homogeneous. We don't
|
||||
have to deal with deployed instances that do not properly do this or that.
|
||||
|
||||
It should still be possible to run psyced with an off-the-mill ldmud and
|
||||
counterwise run a MUD installation with a psyclpc.
|
||||
===============================================================================
|
21
HELP
Normal file
21
HELP
Normal file
|
@ -0,0 +1,21 @@
|
|||
[CONTACT]
|
||||
psyclpc is being maintained by fippo & lynX.
|
||||
|
||||
fippo is available at psyc://goodadvice.pages.de/~fippo
|
||||
or xmpp:fippo@goodadvice.pages.de
|
||||
|
||||
lynX is available as psyc://psyced.org/~lynx
|
||||
|
||||
You can reach us at psyc://psyced.org/@welcome
|
||||
|
||||
[HISTORY]
|
||||
psyclpc is a programming language for intense multi-user network applications
|
||||
such as psyced. it's a recent fork of LDMud with some features and many
|
||||
bug fixes. we kept it compatible to LDMud, so you can run a MUD with it, too.
|
||||
It is available from <http://lpc.psyc.eu>.
|
||||
|
||||
LDMud itself is a continuation of the Amylaar LPMud Gamedriver 3.1.2.
|
||||
See also <http://www.bearnip.com/lars/proj/ldmud.html>.
|
||||
|
||||
psyclpc is released under the GNU LIBRARY GENERAL PUBLIC LICENSE, Version 2.
|
||||
|
323
INSTALL
Normal file
323
INSTALL
Normal file
|
@ -0,0 +1,323 @@
|
|||
Topics covered:
|
||||
|
||||
- psyclpc & LDMud Notes
|
||||
- Unix or Unix-like systems, with additional details for FreeBSD, AIX 3.4,
|
||||
and DEC Ultrix.
|
||||
- IPv6
|
||||
- mySQL
|
||||
- BeOS
|
||||
- Windows 95/98/NT
|
||||
- OS/2
|
||||
|
||||
|
||||
psyclpc & LDMud Notes
|
||||
---------------------
|
||||
|
||||
psyclpc is a variant of the LPC language optimized for psyced.
|
||||
When using this driver distribution "./configure" will restart
|
||||
itself as "./configure --with-setting psyced". This will run
|
||||
configure with all the sane options necessary for a pleasant
|
||||
psyclpc experience tuned to psyced requirements.
|
||||
|
||||
See also http://lpc.psyc.eu and http://about.psyc.eu/psyclpc
|
||||
|
||||
Should you want to make a very traditional driver close to the
|
||||
LDMud original instead, copy your own settings file to the
|
||||
settings directory and run it. All the new functions of psyclpc
|
||||
will then automatically default to LDMud-compatible behaviour.
|
||||
|
||||
Also running "./configure" with *any* parameters will keep it
|
||||
from loading psyced behaviour. Expect psyced not to work with
|
||||
such a driver. It will probably fail with one of these messages:
|
||||
|
||||
psyclpc: Unknown option '--tls-key'.
|
||||
|
||||
Failed to load master object 'secure/master'.
|
||||
|
||||
|
||||
Unix or Unix-like system
|
||||
------------------------
|
||||
|
||||
The driver uses a standard autoconfiguration system which on most
|
||||
systems does all the work for you (for exceptions see below).
|
||||
To prepare the compilation, execute the 'configure' script from
|
||||
within the src/ directory.
|
||||
|
||||
configure checks for a number of site specific settings and uses this
|
||||
information to create the files machine.h (from machine.h.in), Makefile
|
||||
(from Makefile.in) and config.h (from config.h.in). We'll come back to
|
||||
config.h below.
|
||||
|
||||
configure takes a lot of arguments (--help will tell you everything),
|
||||
but the most important are these:
|
||||
|
||||
--prefix=PREFIX: the base directory for the mud installation,
|
||||
defaults to /usr/local/mud .
|
||||
--bindir=DIR: the directory to install the executables in,
|
||||
defaults to ${PREFIX}/bin .
|
||||
--libdir=DIR: the directory where the mudlib is found,
|
||||
defaults to ${PREFIX}/lib .
|
||||
--includedir=DIR: the directory where driver's LPC include files
|
||||
are supposed to live.
|
||||
defaults to ${PREFIX}/include (which is usually wrong).
|
||||
--libexecdir=DIR: the directory where the programs for the ERQ are found,
|
||||
defaults to ${PREFIX}/libexec .
|
||||
|
||||
These settings are written into the Makefile and compiled into the driver,
|
||||
just the mudlib directory setting can be changed with a commandline
|
||||
argument.
|
||||
|
||||
A lot of the drivers parameters can be tweaked for better performance; these
|
||||
parameters are defined in config.h . This file too is created by configure,
|
||||
which provides sensible defaults for all parameters for which no explicite
|
||||
setting is provided. To tweak a setting yourself, pass the argument
|
||||
'--enable-<option>=yes|no' resp. '--with-<option>=<value>' to configure on
|
||||
the commandline.
|
||||
|
||||
Alternatively, the indivial specifications can be collected in a settings
|
||||
file, which is stored in the directory src/settings/. To use the
|
||||
setting file <osb>, give '--with-<osb>' as argument to configure. The
|
||||
file src/settings/default documents the available settings. The setting
|
||||
files are self-executing: './settings/<foo> [<extra-configure-args>]' will
|
||||
start configure with the proper commandline arguments.
|
||||
|
||||
|
||||
The following environment variables can be used to tweak the behaviour
|
||||
of the configure script:
|
||||
CC: the name of the C compiler
|
||||
CFLAGS: compiler flags to be used during the configure script
|
||||
EXTRA_CFLAGS: compiler flags to be used when compiling the game driver
|
||||
LDFLAGS: linker flags to be used by configure and for linking the
|
||||
game driver.
|
||||
|
||||
|
||||
After configuration is finished, you may want to modify the Makefile
|
||||
to fine tune those parameters which are not covered by the configuration.
|
||||
|
||||
The compilation is done using make. Following targets are implemented:
|
||||
|
||||
<none>: compile the driver, named 'psyclpc'.
|
||||
install: compile the driver and install it in ${bindir}
|
||||
utils: compile the utilities, especially the ERQ demon
|
||||
install-utils: compile and install the utilities in ${bindir}
|
||||
install-headers: install the driver header files in ${includedir}.
|
||||
install-all: compile and install everything.
|
||||
|
||||
To actually run this, you need either psyced or a mudlib.
|
||||
|
||||
pthreads:
|
||||
If your systems supports pthreads, --enable-use-pthreads will allow to
|
||||
compile the driver with pthread support. Currently this means that
|
||||
background threads will be used to write data to the network.
|
||||
|
||||
WARNING: pthreads support is still experimental and might crash
|
||||
your driver!
|
||||
|
||||
FreeBSD:
|
||||
When using gcc, it could happen that the compiler aborts with signal 10
|
||||
or 11. The reasons are unknown, but you can restart the compilation
|
||||
process by typing "make" again (and again...).
|
||||
|
||||
AIX 3.4:
|
||||
The native compiler comes in several forms, of which only the
|
||||
basic form 'xlc' works with the configuration script.
|
||||
Start the script as:
|
||||
|
||||
CC=xlc ./configure ...
|
||||
|
||||
DEC Ultrix:
|
||||
Depending on the system configuration you might be unable to
|
||||
compile 'interpret.c' with any kind of optimization at all.
|
||||
The typical symptom is a failure during the compilation with
|
||||
"Error code 1". When that happens, do the following steps:
|
||||
|
||||
- Make as usual until the "interpret" compilation
|
||||
fails. The symptom is "Error code 1".
|
||||
|
||||
- Edit the makefile. Uncomment the compilation
|
||||
line for debugging, and comment the compilation
|
||||
line containing the optimization switches and
|
||||
options.
|
||||
|
||||
- Start the make again. After the "interpret"
|
||||
compilation completes, control-C out of the
|
||||
compilation.
|
||||
|
||||
- Edit the makefile again. Re-comment the line
|
||||
for debugging, and uncomment the line with
|
||||
the optimization switches and options.
|
||||
|
||||
- Start the make again. This time it will
|
||||
complete as expected.
|
||||
|
||||
|
||||
IPv6
|
||||
----
|
||||
If your machine supports IPv6, the driver can be configured to use it: give
|
||||
'--enable-use-ipv6=yes' as argument to the configure script.
|
||||
|
||||
Beware: the driver support is rudimentary, experimental, and may cease to
|
||||
function on the next full moon. Additional work is necessary to really
|
||||
change _all_ address-related functions in driver and mudlibs.
|
||||
|
||||
IPv6 support was implemented by Uwe <mai94cch@studserv.uni-leipzig.de>.
|
||||
|
||||
In order to test IPv6 under Linux you need a 2.2.x kernel (preferably 2.2.10
|
||||
or better) and the inet6 apps. If you use glibc 2.0, you need version 0.35
|
||||
of the inet6 apps, or for glibc 2.1 you need version 0.36. The apps should
|
||||
installed into /usr/inet6.
|
||||
|
||||
The apps are available on ftp.inner.net or on its mirrors, e.g.
|
||||
|
||||
<URL:ftp://6bone.informatik.uni-leipzig.de/pub/ftp.inner.net/pub/ipv6/inet6-apps-0.35.tar.gz>
|
||||
|
||||
resp.
|
||||
|
||||
<URL:ftp://6bone.informatik.uni-leipzig.de/pub/ftp.inner.net/pub/ipv6/inet6-apps0.36.tar.gz>
|
||||
|
||||
Furthermore you need a connection to the 6bone
|
||||
(<URL:http://www.join.uni-muenster.de/>).
|
||||
|
||||
Newer versions of AIX also come with IPv6 support.
|
||||
|
||||
|
||||
mySQL
|
||||
-----
|
||||
If your machine has mySQL installed, the driver can be configured to use
|
||||
it: give '--enable-use-mysql=yes' as argument to the configure script.
|
||||
|
||||
Alternatively, if your mySQL uses an unusual include/library path,
|
||||
the option can be given as '--enable-use-mysql=/unusual/path', which
|
||||
will use the given path as search path for both include and library
|
||||
files in addition to the normal system search paths. The include files will
|
||||
be searched in <path>/include and <path>, the library files will be search
|
||||
in <path>/lib/mysql, <path>/lib, and <path>, in this order.
|
||||
|
||||
The username and password for the mySQL database are specified by
|
||||
the mudlib as arguments to the efun db_connect().
|
||||
|
||||
Use mysqladmin to create any databases you want to provide - the
|
||||
names are later used in the efun db_connect() to connect to
|
||||
the databases.
|
||||
|
||||
|
||||
BeOS
|
||||
----
|
||||
Under BeOS, the driver can be configured and compiled in two ways:
|
||||
|
||||
1. Using the provided configuration files.
|
||||
|
||||
Copy the files machine.h, config.h and Makefile from src/hosts/be/
|
||||
to src/. You may have to edit config.h and Makefile if you have
|
||||
to use a specific mudlib with exotic settings.
|
||||
|
||||
Advantage of this method is that the Makefile allows cross-compilation
|
||||
and covers Be specifics like file icon, type and version.
|
||||
|
||||
2. Use the Unix configure mechanism.
|
||||
|
||||
In general just follow the instructions given for Unix systems, but
|
||||
be aware of the follwing:
|
||||
|
||||
- If the configure script doesn't properly work, try starting it
|
||||
with
|
||||
|
||||
CC="$BE_C_COMPILER" EXTRA_CFLAGS="$BE_DEFAULT_C_FLAGS" ./configure
|
||||
|
||||
or (especially on BeOS R4.5 on PPC) even
|
||||
|
||||
CC=cc EXTRA_CFLAGS="$BE_DEFAULT_C_FLAGS" ./configure
|
||||
|
||||
- the created executable will have neither icon nor type.
|
||||
- cross compilation is not supported.
|
||||
- the Makefile defaults to best optimization which needs a lot
|
||||
of memory during compilation.
|
||||
|
||||
If on driver start you get an error about an unknown hostname or
|
||||
seems to hang, you're missing an /etc/hosts file:
|
||||
- In the network preferences, select a name for you machine,
|
||||
e.g. 'bebox'. The domain name field can be blank.
|
||||
- Copy the /boot/beos/etc/hosts-sample file to /boot/beos/etc/hosts,
|
||||
and edit it to contain at least the following lines:
|
||||
|
||||
127.0.0.1 bebox.my-isp.com bebox
|
||||
127.1 bebox.my-isp.com bebox
|
||||
|
||||
(Note: in the file, every line has to start with the IP address -
|
||||
no leading spaces are allowed).
|
||||
|
||||
With the current networking implementation, the driver is unable
|
||||
to start ERQs. In order to use ERQs, you have to start them manually.
|
||||
|
||||
Other than this, the installation steps are the same as for Unix.
|
||||
|
||||
|
||||
Windows 95/98/NT
|
||||
----------------
|
||||
|
||||
To compile the gamedriver for Windows, you need the 'Cygwin' package,
|
||||
which is a port of gcc, bash, and other GNU/Unix programs. Once it
|
||||
is installed and running, the procedure is the same as under Unix.
|
||||
|
||||
CygWin is available from <URL:http://www.cygwin.com/> or
|
||||
<http://www.redhat.com/software/cygwin/>, and when installing make sure that
|
||||
your installation includes gcc, bash, make, sed, awk, and bison.
|
||||
|
||||
One common pitfall is if the installation does not create the '/bin'
|
||||
directory in which the CygWin executables are expected. A typical
|
||||
error message would be 'make: /bin/sh not found'.
|
||||
|
||||
Solution 1: Create a directory 'bin' in your search path (e.g. c:\bin)
|
||||
and copy all required executables (in this case 'sh.exe') into
|
||||
that directory.
|
||||
|
||||
Solution 2 (this can be done in a script): cd into the directory
|
||||
where the executables are stored, e.g.
|
||||
/compiler/Cygnus/B19/H-i386-cygwin32/bin . In this directory, give
|
||||
the command 'mount $PWD /bin'.
|
||||
|
||||
Solution 3: Use a newer version of Cygwin where this problem apparently
|
||||
has been solved.
|
||||
|
||||
A driver compiled by David Gibbs (ishara@btinternet.com) is available
|
||||
at <URL:http://www.einy.freeserve.co.uk/lpmud.index.html>.
|
||||
|
||||
The following comments were provided by Robert Nurrie(?) who had
|
||||
an misconfigured Cygnus installation (Summer 2000):
|
||||
|
||||
"Make sure you've used the setup.exe you get when clicking the 'install
|
||||
cygwin now' link in the upper right corner of their website, instead of
|
||||
the setup.exe found on the ftp-site.
|
||||
|
||||
Oh, and when you're given the choice of default text file type you
|
||||
should of course chose Dos, as that seems to be the key."
|
||||
|
||||
Brandon Mathis points out, "that to compile under Windows you have to
|
||||
use 'tar -xvfj' and not WinZIP to extract the source".
|
||||
|
||||
|
||||
OS/2
|
||||
----
|
||||
|
||||
The OS/2 port uses the EMX (a gcc version) to compile the gamedriver.
|
||||
To compile the driver, copy the machine.h and Makefile from the hosts/os2
|
||||
directory into the top directory and make as under Unix. The Makefile
|
||||
is configured to install the driver in /mud - edit the variable 'prefix'
|
||||
if you want a different directory.
|
||||
|
||||
Important: the Makefile must be save using the Unix lineend convention,
|
||||
otherwise the make program will stop with an error. In the EPM editor
|
||||
this can be achieved using the 'save -u' command.
|
||||
|
||||
If you have the full GNU suite installed, you can also configure the
|
||||
driver as under Unix. Following caveats regarding the configure script:
|
||||
- the ac_exeext variable may not be set to '.exe' as it should be;
|
||||
- the calls to the program conftest may lack the ${ac_exeext} extension.
|
||||
|
||||
Additionally, configure does not properly recognize the settings for
|
||||
HAVE_GETRUSAGE, GETRUSAGE_RESTRICTED, GETRUSAGE_VIA_SYSCALL and RUSAGE_USEC.
|
||||
Copy these values from the provided machine.h
|
||||
|
||||
To recreate the configure script from configure.in, you need autoconf
|
||||
version 2.50 or newer.
|
||||
|
26
README
Normal file
26
README
Normal file
|
@ -0,0 +1,26 @@
|
|||
The files in this directory are:
|
||||
|
||||
HELP : basics, serves also as source for the man file.
|
||||
README : this file.
|
||||
COPYRIGHT : the copyright of the driver.
|
||||
CREDITS : the list of contributors.
|
||||
HISTORY (removed)
|
||||
CHANGELOG : the last changes in minute detail.
|
||||
COPYING.LIB : the GNU Library Public License.
|
||||
INSTALL : installation hints and notes.
|
||||
FAQ : unfrequently answered questions.
|
||||
psyclpc.1 : manual file.
|
||||
|
||||
doc/ (removed) the documentation is available on the web or
|
||||
in the LDMud distribution.
|
||||
src/ : the driver source
|
||||
pkg/ : additional packages (unsupported and supported) for the driver.
|
||||
mudlib/ : various LPC (example) files.
|
||||
mudlib/sys/:
|
||||
standard include files to copy into your mudlib. Some of these are
|
||||
also used by the src/ files.
|
||||
mud/ (removed) the lp-245 mudlib, and support files for other mudlibs.
|
||||
|
||||
Nice! Somebody made a doxygen of ldmud and posted it on
|
||||
http://lpmuds.net/ldmud/dox/dir_2cb66bf95229e25b825da12cd79535c5.html
|
||||
|
90
TODO
Normal file
90
TODO
Normal file
|
@ -0,0 +1,90 @@
|
|||
FROM LDMUD
|
||||
+ we are glad to find out that Lars is back and working on ldmud! :D
|
||||
- examine & apply: 2320, 2334, 2335, 2336, 2340, 2341
|
||||
|
||||
BUGS
|
||||
- #define USE_EXPAT und JSON werden trotzdem gesetzt in config.h
|
||||
auch wenn configure keine libs gefunden hat (egal, wir verwenden beide nicht)
|
||||
- Because of some funny bug the driver will probably not bind properly
|
||||
to _basic_host_IP as it also needs _basic_host_name and _basic_host_domain
|
||||
to be provided. Hopefully this shortcoming will soon be history.
|
||||
|
||||
WINDOWS SUPPORT
|
||||
+ with the new __NO_SRV__ detection psyclpc compiles under cygwin but it
|
||||
doesn't provide SRV which makes it a suboptimal XMPP router.. just in
|
||||
case you want that.
|
||||
fippo suggests to put http://delta.affinix.com/jdns/ into psyclpc
|
||||
http://www.chiark.greenend.org.uk/~ian/adns/ requires a locally running
|
||||
nameserver.. and i don't think it even runs on cygwin.. other ideas?
|
||||
|
||||
COMPLAINTS
|
||||
-* QA Notice: Package has poor programming practices which may compile
|
||||
* fine but exhibit random runtime failures.
|
||||
* interpret.c:7224: warning: dereferencing type-punned pointer will break strict-aliasing rules
|
||||
|
||||
MISC IDEAS
|
||||
- make more MUD features optional: more d_flag stuff?
|
||||
? USE_RESETS time_of_ref USE_CLEANUP load_id USE_WIZLIST USE_EXPAT USE_EVALUATION_COST
|
||||
- disabling with_input_escape does not disable the input_escape handling source code
|
||||
+ teach ldmud to exec() so that, together with --args, we can run it as a
|
||||
regular daemon without kludgy shellscripts
|
||||
(http://mantis.bearnip.com/view.php?id=55)
|
||||
+ provide a query_shutdown_progress() efun to inform about progress
|
||||
and the intention to either shutdown or restart. maybe even a reason?
|
||||
+ optimize f_lower_case by adding an 'already lowercase' flag to the
|
||||
string data structure
|
||||
+ ldap package erproben und fertigmachen
|
||||
+ put errno() back in
|
||||
+ psyctext() in C ... see psyced/CHANGESTODO for details
|
||||
? bugless says there is an ioctl() to obtain a descriptor's owner uid
|
||||
thus avoid the authlocal /proc hack
|
||||
? have a seperate package for the LPC documentation and update it a bit
|
||||
since ldmud?
|
||||
+ fip thinks we should have a new operator with arguments rather than
|
||||
clone_object and subsequent -> calls. pike doesn't even have the "new"
|
||||
because unlike C++ and LPC it forbids static use of classes (aka "blueprints")
|
||||
+ fippo suggests to look into http://www.hpl.hp.com/personal/Hans_Boehm/gc/leak.html
|
||||
+ DMSG_FLUSH for incremental debug messages :)
|
||||
- for pike compatibility allow string[-1] just like string[<1]
|
||||
|
||||
ENCRYPTION (see http://about.psyc.eu/Talk:Encryption)
|
||||
? link libpurple to this for protocol supports and OTR hahahahaha
|
||||
? or link libotr only?
|
||||
? or is OTR too expensive anyway and we should try SS-TLS?
|
||||
|
||||
USE_RESTORED_OBJECTS
|
||||
+ object names need to be able to be identical to uniforms
|
||||
then it doesn't matter if they came back from persistence as strings
|
||||
as sendmsg() can handle both objects and uniforms - we just need to
|
||||
deal with mappings where both the object and the uniform could be the key..
|
||||
(members & routes of places)
|
||||
|
||||
NETWORKING
|
||||
- http://mantis.bearnip.com/view.php?id=442 (MAX_TEXT)
|
||||
- add_message("%s", "\n*** Text lost in transmission ***\n");
|
||||
should be passed to master instead.
|
||||
+ _length: <eL> somebody implement a new input_to(#'get_data, length).
|
||||
? MAYBE the whole networking should be replaced by libevent!??
|
||||
+ support epoll() / kqueue (or just libevent?)
|
||||
|
||||
? allow port definition from lpc:master.c or even dynamic listen()
|
||||
so we can add port config to the web configurator
|
||||
..egal, machen wir jetzt über psyconf
|
||||
|
||||
CHARSET
|
||||
-? keeping track of charset everywhere to avoid any unnecessary conversion
|
||||
would lead to so much overhead, that occasional unnecessary conversion is
|
||||
the cheaper option. that's why we should convert in the driver close to
|
||||
the network operations:
|
||||
comm.c:3055: if(ip->tls_inited)
|
||||
l = tls_read(ip, ip->text + ip->text_end, (size_t)l);
|
||||
else if (!(ip->tls_want))
|
||||
l = socket_read(ip->socket, ip->text + ip->text_end, ...
|
||||
+ since network read operations are much more efficient than input_to-lines
|
||||
iconv charset conversions should happen right after socket/tls_read()
|
||||
into a pre-buffer, then copy-converted into the interactive's buffer
|
||||
+ outgoing transmissions need to find the same treatment, before
|
||||
socket_write() and also before optional compression.
|
||||
+ socket charset is stored in interactive_s and given by an efun
|
||||
+ charset is compared to SYSTEM_CHARSET which is given by config.h/configure
|
||||
- http://mantis.bearnip.com/view.php?id=117
|
14
etc/README
Normal file
14
etc/README
Normal file
|
@ -0,0 +1,14 @@
|
|||
Miscellaneous files for the driver:
|
||||
|
||||
lpc-mode.el : LPC mode for EMACS, by Vivek Dasmohapatra <vivek@etla.org>
|
||||
lpc.xml : LPC syntax highlighting for Kate, by <Andreas.Klauer@epost.de>
|
||||
lpc.vim : LPC syntax highlighting for vim, maintained by Shizhu
|
||||
Pan <poet@mudbuilder.net>
|
||||
|
||||
savefile-parse.pl: A perl snippet which reads a LPMud savefile and
|
||||
transforms it into a Perl datastructure.
|
||||
|
||||
The following scripts are just working examples - use them to roll your own:
|
||||
|
||||
memusage : A script to analyze OBJ_DUMP.
|
||||
|
382
etc/lpc-mode.el
Normal file
382
etc/lpc-mode.el
Normal file
|
@ -0,0 +1,382 @@
|
|||
;; LPC mode
|
||||
;;
|
||||
;; Emacs Lisp Archive Entry
|
||||
;; Package: lpc-mode
|
||||
;; Filename: lpc-mode.el
|
||||
;; Version: 0.12
|
||||
;; Keywords: languages, LPC
|
||||
;; Author: Vivek Dasmohapatra <vivek@etla.org>
|
||||
;; Maintainer: Vivek Dasmohapatra <vivek@etla.org>
|
||||
;; Created: 2002-08-31
|
||||
;; Description: syntax highlighting/indentation for LPC
|
||||
;; URL: http://rtfm.etla.org/emacs/lpc-mode/
|
||||
;; Compatibility: Emacs21
|
||||
;; Last-Updated: Tue 2002-09-17 23:59:51 +0100
|
||||
|
||||
;; This file is NOT part of GNU Emacs
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program; if not, write to the Free Software
|
||||
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
;; Copyright (C) 2002 Vivek Dasmohapatra <vivek@etla.org>
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; OK Nick: first stab at LPC mode:
|
||||
;; 0.01: 'foo and 'C' should be handled correctly.
|
||||
;; 0.02 ... 0.06: intermediates.
|
||||
;; 0.07: ultra-hairy ({#'[][,&] syntax now scanned for. Bleurgh.
|
||||
;; 0.08: ({ ... }) syntax added as brace-list
|
||||
;; 0.09: rip up and rewrite as a proper cc-mode based mode
|
||||
;; 0.10: miscellaneous bugfixes.
|
||||
;; 0.11: should compile cleanly now _and_ work as well (I hope)
|
||||
;; 0.12: bug in `lpc-font-lock-map' keyword/function definition highlighting
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; HOW TO INSTALL:
|
||||
;;
|
||||
;; ;; either put lpc-mode.el in your load path and use:
|
||||
;; (autoload 'lpc-mode "lpc-mode" t)
|
||||
;;
|
||||
;; ;; or have:
|
||||
;; (autoload 'lpc-mode "/path/to/lpc-mode.el" t)
|
||||
;;
|
||||
;; ;; then:
|
||||
;; (setq auto-mode-alist
|
||||
;; (append '(("\\.lpc$" . lpc-mode)) auto-mode-alist)) )
|
||||
;;
|
||||
;; Nick: You'll have to do similar things to handler.el to get that to
|
||||
;; work, let me know if you need this done.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; elisp-dep-block >>
|
||||
(require 'custom );(defface)
|
||||
(require 'cc-mode );(c-electric-brace)
|
||||
(require 'regexp-opt);(regexp-opt-depth regexp-opt)
|
||||
(require 'font-lock )
|
||||
;;(font-lock-add-keywords font-lock-fontify-region font-lock-mode)
|
||||
;; elisp-dep-block <<
|
||||
|
||||
(defconst lpc-mode-version "0.12")
|
||||
|
||||
(eval-and-compile
|
||||
(defmacro lpc-defsyntax (name doc klist)
|
||||
"Declare a cc-mode syntax variable of lpc-N-keywords and a regex
|
||||
lpc-N-regex to go along with it, based on the keyword list K."
|
||||
(let* ((n name )
|
||||
(d doc )
|
||||
(k klist)
|
||||
(ln (format "lpc-%s-keywords" n))
|
||||
(ld (format "%s (list)" d))
|
||||
(ls (intern ln))
|
||||
(rn (format "lpc-%s-regex" n))
|
||||
(rd (format "%s (regex)" d))
|
||||
(rs (intern rn))
|
||||
(kwds nil))
|
||||
(setq kwds (if (stringp (car k)) k (eval k)))
|
||||
;;(message "%s" (format "%S" kwds))
|
||||
`(progn (defconst ,ls ',kwds ,ld)
|
||||
(defconst ,rs (regexp-opt ',kwds) ,rd)) ))
|
||||
|
||||
(lpc-defsyntax type
|
||||
"LPC primitive type keywords."
|
||||
("int" "mapping" "mixed" "object" "status" "string" "void"))
|
||||
|
||||
(lpc-defsyntax specifier
|
||||
"LPC declaration specifier keywords."
|
||||
("nomask" "private" "public" "static" "varargs"))
|
||||
|
||||
(lpc-defsyntax other-decl
|
||||
"LPC keywords starting other decl-level constructs."
|
||||
("inherit"))
|
||||
|
||||
(lpc-defsyntax block-stmt-1
|
||||
"LPC keywords followed directly by a block."
|
||||
("do" "else"))
|
||||
|
||||
(lpc-defsyntax block-stmt-2
|
||||
"LPC keywords followed by a paren sexp and then by a block."
|
||||
("for" "if" "switch" "while" "foreach"))
|
||||
|
||||
(lpc-defsyntax simple-stmt
|
||||
"LPC statement keywords followed by an expression or nothing."
|
||||
("break" "continue" "return"))
|
||||
|
||||
(lpc-defsyntax label
|
||||
"LPC keywords introducing labels in blocks."
|
||||
("case" "default"))
|
||||
|
||||
(lpc-defsyntax all
|
||||
"LPC keywords."
|
||||
(append lpc-type-keywords
|
||||
lpc-specifier-keywords
|
||||
lpc-other-decl-keywords
|
||||
lpc-block-stmt-1-keywords
|
||||
lpc-block-stmt-2-keywords
|
||||
lpc-simple-stmt-keywords
|
||||
lpc-label-keywords ))
|
||||
|
||||
(lpc-defsyntax default-highlight
|
||||
"LPC keywords (for default highlighting)"
|
||||
(append lpc-specifier-keywords
|
||||
lpc-block-stmt-1-keywords
|
||||
lpc-block-stmt-2-keywords
|
||||
lpc-simple-stmt-keywords ))
|
||||
|
||||
(lpc-defsyntax conditional
|
||||
"LPC conditional keywords"
|
||||
(append lpc-block-stmt-1-keywords lpc-block-stmt-2-keywords))
|
||||
)
|
||||
|
||||
(defconst lpc-comment-start-regex c-C++-comment-start-regexp)
|
||||
(defconst lpc-special-brace-lists '((?{ . ?})) )
|
||||
(defconst lpc-magic-quote-comma '(9))
|
||||
(defconst lpc-magic-symbol-name '(3))
|
||||
|
||||
(defvar lpc-mode-syntax-table nil)
|
||||
(if lpc-mode-syntax-table
|
||||
nil
|
||||
(setq lpc-mode-syntax-table (make-syntax-table))
|
||||
(c-populate-syntax-table lpc-mode-syntax-table)
|
||||
(modify-syntax-entry ?\' "'" lpc-mode-syntax-table) )
|
||||
|
||||
(defun lpc-modify-syntax-at (beg end syntax)
|
||||
"Apply a syntax-property value syntax from beg to end."
|
||||
(if (<= (point-max) end) nil; noop
|
||||
(progn
|
||||
;;(message "(%d x %d) => %S" beg end syntax)
|
||||
(put-text-property beg end 'syntax-table syntax)
|
||||
(put-text-property (1- end) end 'rear-nonsticky t ))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Code by Seth Golub <seth AT cs DOT wustl DOT edu>, 1996-02-01,
|
||||
;; no licence.
|
||||
;;
|
||||
;; modified slightly to bring this up to date, didn't work quite right
|
||||
;; out of the box:
|
||||
(defun lpc-maybe-electric-brace (arg)
|
||||
"Insert character and maybe correct line's indentation."
|
||||
(interactive "P")
|
||||
(if (= last-command-char ?{)
|
||||
(if (= (preceding-char) ?\()
|
||||
(self-insert-command (prefix-numeric-value arg))
|
||||
(c-electric-brace arg))
|
||||
;; (= last-command-char ?})
|
||||
(let (start-point state containing-sexp)
|
||||
(save-excursion (beginning-of-defun)
|
||||
(setq start-point (point)))
|
||||
(save-excursion (setq state (parse-partial-sexp (point) start-point 0)))
|
||||
(setq containing-sexp (car (cdr state)))
|
||||
(if (and containing-sexp (save-excursion
|
||||
(goto-char (1- containing-sexp))
|
||||
(looking-at "(")))
|
||||
(progn
|
||||
(self-insert-command (prefix-numeric-value arg))
|
||||
(lpc-scan-magic-quote))
|
||||
(c-electric-brace arg)))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defconst lpc-magic-quote-regex "({\\s-*#'\\([^\\s-\n,}]+\\|,\\)\\s-*[,}]")
|
||||
|
||||
(defun lpc-magic-comma-p (pt)
|
||||
(let ((bol nil) (eol nil) (pos nil) (ret nil))
|
||||
(save-excursion
|
||||
(goto-char pt)
|
||||
(end-of-line)
|
||||
(setq eol (point))
|
||||
(beginning-of-line)
|
||||
(setq bol (point))
|
||||
(while (and (not ret)
|
||||
(setq pos (re-search-forward lpc-magic-quote-regex eol t)))
|
||||
;;(message "magic pattern at %d/%d" (1- pos) pt)
|
||||
(if (/= (1- pos) pt) nil
|
||||
(setq ret (list (- (match-beginning 1) 1)
|
||||
(match-beginning 1)
|
||||
(match-end 1)
|
||||
bol)) ) )) ret))
|
||||
|
||||
(defun lpc-scan-magic-quotes ()
|
||||
(save-excursion
|
||||
(let ((qpos nil) (wbeg nil) (wend nil))
|
||||
(while (re-search-forward lpc-magic-quote-regex nil t)
|
||||
(setq qpos (+ (match-beginning 0) 3)
|
||||
wbeg (match-beginning 1)
|
||||
wend (match-end 1))
|
||||
(lpc-modify-syntax-at qpos (1+ qpos) lpc-magic-quote-comma)
|
||||
(lpc-modify-syntax-at wbeg wend lpc-magic-symbol-name)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun lpc-scan-magic-quote ()
|
||||
(save-excursion
|
||||
(let ((coord nil) (qpos nil) (wbeg nil) (wend nil) (bol nil))
|
||||
(if (setq coord (lpc-magic-comma-p (1- (point))))
|
||||
(progn
|
||||
(setq qpos (car coord)
|
||||
wbeg (cadr coord)
|
||||
wend (car (cddr coord))
|
||||
bol (cadr (cddr coord)))
|
||||
;;(message "magic pattern at (%d %d %d)" qpos wbeg wend)
|
||||
(lpc-modify-syntax-at qpos (1+ qpos) lpc-magic-quote-comma)
|
||||
(lpc-modify-syntax-at wbeg wend lpc-magic-symbol-name)
|
||||
(font-lock-fontify-region bol wend) )
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun lpc-maybe-quote-ref (arg)
|
||||
"Kludge to work around multiple syntactic meanings of `,' `[' et al in LPC."
|
||||
(interactive "P")
|
||||
(self-insert-command (prefix-numeric-value arg))
|
||||
(lpc-scan-magic-quote) )
|
||||
|
||||
(defvar lpc-mode-map nil "Keymap for LPC mode buffers.")
|
||||
(if lpc-mode-map
|
||||
nil
|
||||
(setq lpc-mode-map (c-make-inherited-keymap))
|
||||
(define-key lpc-mode-map "\C-c:" 'c-scope-operator)
|
||||
(define-key lpc-mode-map "{" 'lpc-maybe-electric-brace)
|
||||
(define-key lpc-mode-map "}" 'lpc-maybe-electric-brace)
|
||||
(define-key lpc-mode-map "," 'lpc-maybe-quote-ref)
|
||||
(define-key lpc-mode-map "\C-c\C-e" 'c-macro-expand)
|
||||
)
|
||||
|
||||
(defvar lpc-mode-hook nil)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; font-lock support:
|
||||
|
||||
(defvar lpc-reference-face 'lpc-reference-face)
|
||||
(defface lpc-reference-face
|
||||
'((((class color) (background dark)) (:foreground "bisque" ))
|
||||
(((class color) (background light)) (:foreground "dark blue")))
|
||||
"LPC mode face for quoted symbols")
|
||||
|
||||
(defconst lpc-type-depth (regexp-opt-depth lpc-type-regex))
|
||||
|
||||
(defconst lpc-font-lock-map
|
||||
(append
|
||||
c-font-lock-keywords-1
|
||||
(list
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; what follows is mostly ripped from font-lock.el, mostly...
|
||||
`(eval . (cons (concat "\\<\\(" ,lpc-type-regex "\\)\\>")
|
||||
'font-lock-type-face))
|
||||
|
||||
(concat "\\<\\(" lpc-default-highlight-regex "\\)\\>")
|
||||
|
||||
'("\\<\\(case\\)\\>" (1 font-lock-keyword-face)
|
||||
("\\(-[0-9]+\\|\\sw+\\)"
|
||||
;; Return limit of search.
|
||||
(save-excursion (skip-chars-forward "^:\n") (point))
|
||||
nil
|
||||
(1 font-lock-constant-face nil t)))
|
||||
|
||||
'(":" ("^[ \t]*\\(\\sw+\\)[ \t]*:[ \t]*$"
|
||||
(beginning-of-line) (end-of-line)
|
||||
(1 font-lock-constant-face)))
|
||||
|
||||
`(eval . (list
|
||||
(concat "\\<\\(" ,lpc-type-regex "\\)\\>"
|
||||
"\\([ \t*&]+\\sw+\\>\\)*")
|
||||
;; Fontify each declaration item.
|
||||
(list
|
||||
'font-lock-match-c-style-declaration-item-and-skip-to-next
|
||||
;; Start with point after all type specifiers.
|
||||
(list 'goto-char
|
||||
(list 'or
|
||||
(list 'match-beginning
|
||||
(+ ,lpc-type-depth 2))
|
||||
'(match-end 1)))
|
||||
;; Finish with point after first type specifier.
|
||||
'(goto-char (match-end 1))
|
||||
;; Fontify as a variable or function name.
|
||||
'(1 (if (match-beginning 2)
|
||||
font-lock-function-name-face
|
||||
font-lock-variable-name-face)))))
|
||||
|
||||
;; Fontify anything at beginning of line as a declaration or definition.
|
||||
'("^\\(\\sw+\\)\\>\\([ \t*]+\\sw+\\>\\)*"
|
||||
(1 font-lock-type-face)
|
||||
(font-lock-match-c-style-declaration-item-and-skip-to-next
|
||||
(goto-char (or (match-beginning 2) (match-end 1))) nil
|
||||
(1 (if (match-beginning 2)
|
||||
font-lock-function-name-face
|
||||
font-lock-variable-name-face))))
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; and now native LPC highlighting:
|
||||
'("\\('.'\\|'\\\\.'\\)" 1 font-lock-string-face keep)
|
||||
;; lambda thingies
|
||||
'("{\\s-*\\(#\\)" 1 font-lock-builtin-face keep)
|
||||
'("'\\([^}, \t;]+\\)" 1 lpc-reference-face keep)
|
||||
'("'\\(,\\)[,} \t\n]" 1 lpc-reference-face keep)
|
||||
;;
|
||||
'("\\(\\binherit\\)\\s-+\\s\".+\";" 1 font-lock-builtin-face t)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun lpc-set-font-lock-defaults ()
|
||||
"Set up LPC mode font-lock stuff."
|
||||
(let ((font-lock-defaults '(lpc-font-lock-map
|
||||
nil
|
||||
nil
|
||||
((?_ . "w") (?\' . "'"))
|
||||
beginning-of-defun
|
||||
(font-lock-mark-block-function . mark-defun))))
|
||||
(font-lock-set-defaults)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; bring it all together:
|
||||
|
||||
(defun lpc-mode ()
|
||||
(interactive)
|
||||
(c-initialize-cc-mode)
|
||||
(kill-all-local-variables)
|
||||
(set-syntax-table lpc-mode-syntax-table)
|
||||
(make-variable-buffer-local 'parse-sexp-lookup-properties)
|
||||
(set 'parse-sexp-lookup-properties t)
|
||||
(setq major-mode 'lpc-mode
|
||||
mode-name "LPC")
|
||||
(use-local-map lpc-mode-map)
|
||||
(c-common-init)
|
||||
(setq c-keywords (c-identifier-re lpc-all-regex)
|
||||
c-special-brace-lists lpc-special-brace-lists
|
||||
comment-start "// "
|
||||
comment-end ""
|
||||
c-conditional-key lpc-conditional-regex
|
||||
c-comment-start-regexp lpc-comment-start-regex
|
||||
c-extra-toplevel-key lpc-other-decl-regex
|
||||
;; c-class-key nil ;; cannot set this to nil or ""
|
||||
c-method-key nil
|
||||
c-baseclass-key nil
|
||||
c-recognize-knr-p nil
|
||||
c-lambda-key nil
|
||||
c-inexpr-block-key nil
|
||||
c-inexpr-class-key nil)
|
||||
(lpc-set-font-lock-defaults)
|
||||
(lpc-scan-magic-quotes)
|
||||
(if (not noninteractive)
|
||||
(turn-on-font-lock)
|
||||
(let ((font-lock-mode t) (noninteractive nil))
|
||||
(turn-on-font-lock)))
|
||||
(run-hooks 'c-mode-common-hook)
|
||||
(run-hooks 'lpc-mode-hook)
|
||||
(c-update-modeline)
|
||||
)
|
||||
|
||||
(provide 'lpc-mode)
|
||||
;; lpc-mode.el ends here
|
447
etc/lpc.vim
Normal file
447
etc/lpc.vim
Normal file
|
@ -0,0 +1,447 @@
|
|||
" Vim syntax file
|
||||
" Language: LPC
|
||||
" Maintainer: Shizhu Pan <poet@mudbuilder.net>
|
||||
" URL: http://poet.tomud.com/pub/lpc.vim.bz2
|
||||
" Last Change: 2003 May 11
|
||||
" Comments: If you are using Vim 6.2 or later, see :h lpc.vim for
|
||||
" file type recognizing, if not, you had to use modeline.
|
||||
" Changed for LDMud 3.2 and 3.3, Coogan@Tubmud, 02-Sep-2003
|
||||
|
||||
|
||||
" Nodule: This is the start nodule. {{{1
|
||||
|
||||
" For version 5.x: Clear all syntax items
|
||||
" For version 6.x: Quit when a syntax file was already loaded
|
||||
if version < 600
|
||||
syntax clear
|
||||
elseif exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
" Nodule: Keywords {{{1
|
||||
|
||||
" LPC keywords
|
||||
" keywords should always be highlighted so "contained" is not used.
|
||||
syn cluster lpcKeywdGrp contains=lpcConditional,lpcLabel,lpcOperator,lpcRepeat,lpcStatement,lpcModifier,lpcReserved
|
||||
|
||||
syn keyword lpcConditional if else switch
|
||||
syn keyword lpcLabel case default
|
||||
syn keyword lpcOperator catch efun in inherit nolog publish
|
||||
syn keyword lpcRepeat do for foreach while
|
||||
syn keyword lpcStatement break continue return function
|
||||
|
||||
syn match lpcEfunError /efun[^:]/ display
|
||||
|
||||
" Illegal to use keyword as function
|
||||
" It's not working, maybe in the next version.
|
||||
syn keyword lpcKeywdError contained if for foreach return switch while
|
||||
|
||||
" These are keywords only because they take lvalue or type as parameter,
|
||||
" so these keywords should only be used as function but cannot be names of
|
||||
" user-defined functions.
|
||||
" syn keyword lpcKeywdFunc new parse_command sscanf time_expression
|
||||
|
||||
" Nodule: Type and modifiers {{{1
|
||||
|
||||
" Type names list.
|
||||
|
||||
" Special types
|
||||
syn keyword lpcType void mixed unknown
|
||||
" Scalar/Value types.
|
||||
syn keyword lpcType int float string status
|
||||
" Pointer types.
|
||||
syn keyword lpcType array function mapping object struct
|
||||
" Other types.
|
||||
syn keyword lpcType closure funcall
|
||||
|
||||
|
||||
" Type modifier.
|
||||
syn keyword lpcModifier nomask private public
|
||||
syn keyword lpcModifier varargs virtual
|
||||
|
||||
" sensible modifiers
|
||||
syn keyword lpcModifier nosave protected static
|
||||
|
||||
|
||||
" Nodule: Applies {{{1
|
||||
|
||||
" Match a function declaration or function pointer
|
||||
syn match lpcApplyDecl excludenl /->\h\w*(/me=e-1 contains=lpcApplies transparent display
|
||||
|
||||
" We should note that in func_spec.c the efun definition syntax is so
|
||||
" complicated that I use such a long regular expression to describe.
|
||||
syn match lpcLongDecl excludenl /\(\s\|\*\)\h\+\s\h\+(/me=e-1 contains=@lpcEfunGroup,lpcType,@lpcKeywdGrp transparent display
|
||||
|
||||
" this is form for all functions
|
||||
" ->foo() form had been excluded
|
||||
syn match lpcFuncDecl excludenl /\h\w*(/me=e-1 contains=lpcApplies,@lpcEfunGroup,lpcKeywdError transparent display
|
||||
|
||||
" The (: :) parenthesis or $() forms a function pointer
|
||||
syn match lpcFuncName /(:\s*\h\+\s*:)/me=e-1 contains=lpcApplies,@lpcEfunGroup transparent display contained
|
||||
syn match lpcFuncName /(:\s*\h\+,/ contains=lpcApplies,@lpcEfunGroup transparent display contained
|
||||
syn match lpcFuncName /\$(\h\+)/ contains=lpcApplies,@lpcEfunGroup transparent display contained
|
||||
|
||||
" Applies list.
|
||||
" system applies for compat mode
|
||||
syn keyword lpcApplies contained add_weight can_put_and_get drop get prevent_insert query_weight
|
||||
" system applies for native mode
|
||||
syn keyword lpcApplies contained create
|
||||
" system applies
|
||||
syn keyword lpcApplies contained __INIT catch_msg clean_up exit heart_beat id init reset
|
||||
" interactive
|
||||
syn keyword lpcApplies contained catch_tell logon modify_command
|
||||
" master applies
|
||||
syn keyword lpcApplies contained compile_object connect creator_file dangling_lfun_closure disconnect epilog external_master_reload flag get_bb_uid get_ed_buffer_save_file_name get_master_uid get_simul_efun get_wiz_name heart_beat_error inaugurate_master include_file inherit_file log_error make_path_absolute notify_shutdown preload prepare_destruct printf_obj_name privilege_violation query_allow_shadow quota_demon reactivate_destructed_master receive_imp receive_udp remove_player retrieve_ed_setup runtime_error save_ed_setup slow_shutdown stale_erq
|
||||
syn keyword lpcApplies contained valid_exec valid_query_snoop valid_read valid_seteuid valid_snoop valid_trace valid_write
|
||||
" parsing
|
||||
syn keyword lpcApplies contained parse_command_adjectiv_id_list parse_command_all_word parse_command_id_list parse_command_plural_id_list parse_command_prepos_list
|
||||
|
||||
|
||||
" Nodule: Efuns {{{1
|
||||
|
||||
syn cluster lpcEfunGroup contains=lpc_efuns,lpcOldEfuns,lpcNewEfuns,lpcKeywdFunc,lpcCompatEfuns,lpcNativeEfuns,lpcSimulEfuns
|
||||
|
||||
" syn match lpcErrFunc /#`\h\w*/
|
||||
" Shell compatible first line comment.
|
||||
" syn region lpcCommentFunc start=/^#!/ end=/$/
|
||||
|
||||
" efuns which are [to be] removed in newer versions of LDMud.
|
||||
syn keyword lpcOldEfuns contained add_verb add_xverb allocate_mapping copy_mapping efun308 file_name filter_array filter_mapping m_sizeof map_array map_mapping mapping_contains member_array parse_command query_imp_port send_imp set_auto_include_string transfer
|
||||
|
||||
" new efuns of LDMud 3.3
|
||||
syn keyword lpcNewEfuns contained baseof call_direct call_direct_resolved match_command md5_crypt regmatch
|
||||
syn keyword lpcNewEfuns contained start_mccp_compress end_mccp_compress query_mccp query_mccp_stats
|
||||
syn keyword lpcNewEfuns contained pg_connect pg_query pg_pending pg_close
|
||||
syn keyword lpcNewEfuns contained struct_info structp to_struct
|
||||
syn keyword lpcNewEfuns contained tls_query_connection_state tls_query_connection_info tls_init_connection tls_deinit_connection tls_error
|
||||
|
||||
syn keyword lpcCompatEfuns contained creator
|
||||
syn keyword lpcNativeEfuns contained export_uid geteuid getuid seteuid
|
||||
|
||||
" simul efuns, add your simul efuns here
|
||||
syn keyword lpcSimulEfuns contained transfer
|
||||
|
||||
" LPC efuns list.
|
||||
" Efuns list {{{2
|
||||
syn keyword lpc_efuns contained abs acos add_action all_environment all_inventory allocate allocate_mapping and_bits apply asin assoc atan atan2 attach_erq_demon
|
||||
syn keyword lpc_efuns contained binary_message bind_lambda blueprint break_point
|
||||
syn keyword lpc_efuns contained call_other call_out call_out_info call_resolved caller_stack caller_stack_depth capitalize cat catch ceil clear_bit clone_object clonep clones closurep command command_stack command_stack_depth copy copy_bits copy_file cos count_bits crypt ctime
|
||||
syn keyword lpc_efuns contained db_affected_rows db_close db_coldefs db_connect db_conv_string db_error db_exec db_fetch db_handles db_insert_id debug_info debug_message deep_copy deep_inventory destruct disable_commands
|
||||
syn keyword lpc_efuns contained ed enable_commands environment exec execute_command exp expand_define explode extern_call extract
|
||||
syn keyword lpc_efuns contained file_size filter filter_indices filter_objects find_call_out find_input_to find_object first_inventory floatp floor funcall function_exists functionlist
|
||||
syn keyword lpc_efuns contained garbage_collection get_dir get_error_file get_eval_cost get_extra_wizinfo get_type_info gmtime
|
||||
syn keyword lpc_efuns contained heart_beat_info
|
||||
syn keyword lpc_efuns contained implode include_list inherit_list input_to input_to_info insert_alist interactive intersect_alist intp invert_bits
|
||||
syn keyword lpc_efuns contained lambda last_bit last_instructions limited living load_name load_object localtime log lower_case
|
||||
syn keyword lpc_efuns contained m_add m_allocate m_contains m_delete m_entry m_indices m_reallocate m_values make_shared_string map map_indices map_objects mappingp max md5 member min mkdir mkmapping move_object
|
||||
syn keyword lpc_efuns contained negate next_bit next_inventory notify_fail
|
||||
syn keyword lpc_efuns contained object_info object_name object_time objectp or_bits order_alist
|
||||
syn keyword lpc_efuns contained pointerp pow present present_clone previous_object printf process_string program_name program_time
|
||||
syn keyword lpc_efuns contained query_actions query_command query_editing query_idle query_input_pending query_ip_name query_ip_number query_limits query_load_average query_mud_port query_notify_fail query_once_interactive query_shadowing query_snoop query_udp_port query_verb quote
|
||||
syn keyword lpc_efuns contained raise_error random read_bytes read_file referencep regexp regexplode regmatch regreplace remove_action remove_call_out remove_input_to remove_interactive rename rename_object replace_program restore_object restore_value rm rmdir rmember rusage
|
||||
syn keyword lpc_efuns contained save_object save_value say send_erq send_udp set_bit set_buffer_size set_combine_charset set_connection_charset set_driver_hook set_environment set_extra_wizinfo set_extra_wizinfo_size set_heart_beat set_is_wizard set_light set_limits set_modify_command set_next_reset set_prompt set_this_object set_this_player sgn shadow shutdown sin sizeof slice_array snoop sort_array sprintf sqrt sscanf stringp strlen strrstr strstr swap symbol_function symbol_variable symbolp
|
||||
syn keyword lpc_efuns contained tail tan tell_object tell_room terminal_colour test_bit this_interactive this_object this_player throw time to_array to_float to_int to_object to_string trace traceprefix transpose_array trim typeof
|
||||
syn keyword lpc_efuns contained unbound_lambda unique_array unmkmapping unquote unshadow upper_case users utime
|
||||
syn keyword lpc_efuns contained variable_exists variable_list
|
||||
syn keyword lpc_efuns contained walk_mapping widthof wizlist_info write write_bytes write_file
|
||||
syn keyword lpc_efuns contained xor_bits
|
||||
|
||||
" Nodule: Constants {{{1
|
||||
|
||||
" LPC Constants.
|
||||
" like keywords, constants are always highlighted, be careful to choose only
|
||||
" the constants we used to add to this list.
|
||||
syn keyword lpcConstant LPC3 __LDMUD__ __EUIDS__ COMPAT_FLAG __COMPAT_MODE__ __STRICT_EUIDS__ __FILENAME_SPACES__ __MASTER_OBJECT__ __FILE__ __LINE__ __DIR__ __PATH__ __VERSION__ __VERSION_MAJOR__ __VERSION_MINOR__ __VERSION_MICRO__ __VERSION_PATCH__ __DOMAIN_NAME__ __HOST_IP_NUMBER__ __HOST_NAME__ __MAX_RECURSION__ __MAX_EVAL_COST__ __CATCH_EVAL_COST__ __MASTER_EVAL_COST__ __RESET_TIME__ __CLEANUP_TIME__ __EFUN_DEFINED__ __DRIVER_LOG__ __WIZLIST__ __INT_MAX__ __INT_MIN__ __FLOAT_MAX__ __FLOAT_MIN__ __MAX_MALLOC__
|
||||
|
||||
|
||||
" Nodule: Todo for this file. {{{1
|
||||
|
||||
" TODO : need to check for LPC4 syntax and other series of LPC besides
|
||||
" v22, b21 and l32, if you had a good idea, contact me at poet@mudbuilder.net
|
||||
" and I will be appreciated about that.
|
||||
|
||||
" Notes about some FAQ:
|
||||
"
|
||||
" About variables : We adopts the same behavior for C because almost all the
|
||||
" LPC programmers are also C programmers, so we don't need separate settings
|
||||
" for C and LPC. That is the reason why I don't change variables like
|
||||
" "c_no_utf"s to "lpc_no_utf"s.
|
||||
"
|
||||
" Copy : Some of the following seems to be copied from c.vim but not quite
|
||||
" the same in details because the syntax for C and LPC is different.
|
||||
"
|
||||
" Color scheme : this syntax file had been thouroughly tested to work well
|
||||
" for all of the dark-backgrounded color schemes Vim has provided officially,
|
||||
" and it should be quite Ok for all of the bright-backgrounded color schemes,
|
||||
" of course it works best for the color scheme that I am using, download it
|
||||
" from http://poet.tomud.com/pub/ps_color.vim.bz2 if you want to try it.
|
||||
"
|
||||
|
||||
" Nodule: String and Character {{{1
|
||||
|
||||
|
||||
" String and Character constants
|
||||
" Highlight special characters (those which have a backslash) differently
|
||||
syn match lpcSpecial display contained "\\\(x\x\+\|\o\{1,3}\|.\|$\)"
|
||||
if !exists("c_no_utf")
|
||||
syn match lpcSpecial display contained "\\\(u\x\{4}\|U\x\{8}\)"
|
||||
endif
|
||||
|
||||
" LPC version of sprintf() format,
|
||||
syn match lpcFormat display "%\(\d\+\)\=[-+ |=#@:.]*\(\d\+\)\=\('\I\+'\|'\I*\\'\I*'\)\=[OsdicoxXf]" contained
|
||||
syn match lpcFormat display "%%" contained
|
||||
syn region lpcString start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=lpcSpecial,lpcFormat
|
||||
" lpcCppString: same as lpcString, but ends at end of line
|
||||
syn region lpcCppString start=+L\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=lpcSpecial,lpcFormat
|
||||
|
||||
" LPC preprocessor for the text formatting short cuts
|
||||
" Thanks to Dr. Charles E. Campbell <cec@gryphon.gsfc.nasa.gov>
|
||||
" he suggests the best way to do this.
|
||||
syn region lpcTextString start=/@\z(\h\w*\)$/ end=/^\z1/ contains=lpcSpecial
|
||||
syn region lpcArrayString start=/@@\z(\h\w*\)$/ end=/^\z1/ contains=lpcSpecial
|
||||
|
||||
" Character
|
||||
syn match lpcCharacter "L\='[^\\]'"
|
||||
syn match lpcCharacter "L'[^']*'" contains=lpcSpecial
|
||||
syn match lpcSpecialError "L\='\\[^'\"?\\abefnrtv]'"
|
||||
syn match lpcSpecialCharacter "L\='\\['\"?\\abefnrtv]'"
|
||||
syn match lpcSpecialCharacter display "L\='\\\o\{1,3}'"
|
||||
syn match lpcSpecialCharacter display "'\\x\x\{1,2}'"
|
||||
syn match lpcSpecialCharacter display "L'\\x\x\+'"
|
||||
|
||||
" Nodule: White space {{{1
|
||||
|
||||
" when wanted, highlight trailing white space
|
||||
if exists("c_space_errors")
|
||||
if !exists("c_no_trail_space_error")
|
||||
syn match lpcSpaceError display excludenl "\s\+$"
|
||||
endif
|
||||
if !exists("c_no_tab_space_error")
|
||||
syn match lpcSpaceError display " \+\t"me=e-1
|
||||
endif
|
||||
endif
|
||||
|
||||
" Nodule: Parenthesis and brackets {{{1
|
||||
|
||||
" catch errors caused by wrong parenthesis and brackets
|
||||
syn cluster lpcParenGroup contains=lpcParenError,lpcIncluded,lpcSpecial,lpcCommentSkip,lpcCommentString,lpcComment2String,@lpcCommentGroup,lpcCommentStartError,lpcUserCont,lpcUserLabel,lpcBitField,lpcCommentSkip,lpcOctalZero,lpcCppOut,lpcCppOut2,lpcCppSkip,lpcFormat,lpcNumber,lpcFloat,lpcOctal,lpcOctalError,lpcNumbersCom
|
||||
syn region lpcParen transparent start='(' end=')' contains=ALLBUT,@lpcParenGroup,lpcCppParen,lpcErrInBracket,lpcCppBracket,lpcCppString,@lpcEfunGroup,lpcApplies,lpcKeywdError
|
||||
" lpcCppParen: same as lpcParen but ends at end-of-line; used in lpcDefine
|
||||
syn region lpcCppParen transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@lpcParenGroup,lpcErrInBracket,lpcParen,lpcBracket,lpcString,@lpcEfunGroup,lpcApplies,lpcKeywdError
|
||||
syn match lpcParenError display ")"
|
||||
syn match lpcParenError display "\]"
|
||||
" for LPC:
|
||||
" Here we should consider the array ({ }) parenthesis and mapping ([ ])
|
||||
" parenthesis and multiset (< >) parenthesis.
|
||||
syn match lpcErrInParen display contained "[^^]{"ms=s+1
|
||||
syn match lpcErrInParen display contained "\(}\|\]\)[^)]"me=e-1
|
||||
syn region lpcBracket transparent start='\[' end=']' contains=ALLBUT,@lpcParenGroup,lpcErrInParen,lpcCppParen,lpcCppBracket,lpcCppString,@lpcEfunGroup,lpcApplies,lpcFuncName,lpcKeywdError
|
||||
" lpcCppBracket: same as lpcParen but ends at end-of-line; used in lpcDefine
|
||||
syn region lpcCppBracket transparent start='\[' skip='\\$' excludenl end=']' end='$' contained contains=ALLBUT,@lpcParenGroup,lpcErrInParen,lpcParen,lpcBracket,lpcString,@lpcEfunGroup,lpcApplies,lpcFuncName,lpcKeywdError
|
||||
syn match lpcErrInBracket display contained "[);{}]"
|
||||
|
||||
" Nodule: Numbers {{{1
|
||||
|
||||
" integer number, or floating point number without a dot and with "f".
|
||||
syn case ignore
|
||||
syn match lpcNumbers display transparent "\<\d\|\.\d" contains=lpcNumber,lpcFloat,lpcOctalError,lpcOctal
|
||||
" Same, but without octal error (for comments)
|
||||
syn match lpcNumbersCom display contained transparent "\<\d\|\.\d" contains=lpcNumber,lpcFloat,lpcOctal
|
||||
syn match lpcNumber display contained "\d\+\(u\=l\{0,2}\|ll\=u\)\>"
|
||||
" hex number
|
||||
syn match lpcNumber display contained "0x\x\+\(u\=l\{0,2}\|ll\=u\)\>"
|
||||
" Flag the first zero of an octal number as something special
|
||||
syn match lpcOctal display contained "0\o\+\(u\=l\{0,2}\|ll\=u\)\>" contains=lpcOctalZero
|
||||
syn match lpcOctalZero display contained "\<0"
|
||||
syn match lpcFloat display contained "\d\+f"
|
||||
" floating point number, with dot, optional exponent
|
||||
syn match lpcFloat display contained "\d\+\.\d*\(e[-+]\=\d\+\)\=[fl]\="
|
||||
" floating point number, starting with a dot, optional exponent
|
||||
syn match lpcFloat display contained "\.\d\+\(e[-+]\=\d\+\)\=[fl]\=\>"
|
||||
" floating point number, without dot, with exponent
|
||||
syn match lpcFloat display contained "\d\+e[-+]\=\d\+[fl]\=\>"
|
||||
" flag an octal number with wrong digits
|
||||
syn match lpcOctalError display contained "0\o*[89]\d*"
|
||||
syn case match
|
||||
|
||||
" Nodule: Comment string {{{1
|
||||
|
||||
" lpcCommentGroup allows adding matches for special things in comments
|
||||
syn keyword lpcTodo contained TODO FIXME XXX
|
||||
syn cluster lpcCommentGroup contains=lpcTodo
|
||||
|
||||
if exists("c_comment_strings")
|
||||
" A comment can contain lpcString, lpcCharacter and lpcNumber.
|
||||
syntax match lpcCommentSkip contained "^\s*\*\($\|\s\+\)"
|
||||
syntax region lpcCommentString contained start=+L\=\\\@<!"+ skip=+\\\\\|\\"+ end=+"+ end=+\*/+me=s-1 contains=lpcSpecial,lpcCommentSkip
|
||||
syntax region lpcComment2String contained start=+L\=\\\@<!"+ skip=+\\\\\|\\"+ end=+"+ end="$" contains=lpcSpecial
|
||||
syntax region lpcCommentL start="//" skip="\\$" end="$" keepend contains=@lpcCommentGroup,lpcComment2String,lpcCharacter,lpcNumbersCom,lpcSpaceError
|
||||
syntax region lpcComment matchgroup=lpcCommentStart start="/\*" matchgroup=NONE end="\*/" contains=@lpcCommentGroup,lpcCommentStartError,lpcCommentString,lpcCharacter,lpcNumbersCom,lpcSpaceError
|
||||
else
|
||||
syn region lpcCommentL start="//" skip="\\$" end="$" keepend contains=@lpcCommentGroup,lpcSpaceError
|
||||
syn region lpcComment matchgroup=lpcCommentStart start="/\*" matchgroup=NONE end="\*/" contains=@lpcCommentGroup,lpcCommentStartError,lpcSpaceError
|
||||
endif
|
||||
" keep a // comment separately, it terminates a preproc. conditional
|
||||
syntax match lpcCommentError display "\*/"
|
||||
syntax match lpcCommentStartError display "/\*"me=e-1 contained
|
||||
|
||||
" Nodule: Pre-processor {{{1
|
||||
|
||||
syn region lpcPreCondit start="^\s*#\s*\(if\|ifdef\|ifndef\|elif\)\>" skip="\\$" end="$" end="//"me=s-1 contains=lpcComment,lpcCppString,lpcCharacter,lpcCppParen,lpcParenError,lpcNumbers,lpcCommentError,lpcSpaceError
|
||||
syn match lpcPreCondit display "^\s*#\s*\(else\|endif\)\>"
|
||||
if !exists("c_no_if0")
|
||||
syn region lpcCppOut start="^\s*#\s*if\s\+0\+\>" end=".\|$" contains=lpcCppOut2
|
||||
syn region lpcCppOut2 contained start="0" end="^\s*#\s*\(endif\>\|else\>\|elif\>\)" contains=lpcSpaceError,lpcCppSkip
|
||||
syn region lpcCppSkip contained start="^\s*#\s*\(if\>\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*#\s*endif\>" contains=lpcSpaceError,lpcCppSkip
|
||||
endif
|
||||
syn region lpcIncluded display contained start=+"+ skip=+\\\\\|\\"+ end=+"+
|
||||
syn match lpcIncluded display contained "<[^>]*>"
|
||||
syn match lpcInclude display "^\s*#\s*include\>\s*["<]" contains=lpcIncluded
|
||||
syn match lpcLineSkip "\\$"
|
||||
syn cluster lpcPreProcGroup contains=lpcPreCondit,lpcIncluded,lpcInclude,lpcDefine,lpcErrInParen,lpcErrInBracket,lpcUserLabel,lpcSpecial,lpcOctalZero,lpcCppOut,lpcCppOut2,lpcCppSkip,lpcFormat,lpcNumber,lpcFloat,lpcOctal,lpcOctalError,lpcNumbersCom,lpcString,lpcCommentSkip,lpcCommentString,lpcComment2String,@lpcCommentGroup,lpcCommentStartError,lpcParen,lpcBracket,lpcMulti,lpcKeywdError
|
||||
syn region lpcDefine start="^\s*#\s*\(define\|undef\)\>" skip="\\$" end="$" end="//"me=s-1 contains=ALLBUT,@lpcPreProcGroup
|
||||
|
||||
if exists("lpc_pre_v22")
|
||||
syn region lpcPreProc start="^\s*#\s*\(pragma\>\|echo\>\)" skip="\\$" end="$" keepend contains=ALLBUT,@lpcPreProcGroup
|
||||
else
|
||||
syn region lpcPreProc start="^\s*#\s*\(pragma\>\|echo\>\|warn\>\|error\>\)" skip="\\$" end="$" keepend contains=ALLBUT,@lpcPreProcGroup
|
||||
endif
|
||||
|
||||
" Nodule: User labels {{{1
|
||||
|
||||
" Highlight Labels
|
||||
" User labels in LPC is not allowed, only "case x" and "default" is supported
|
||||
syn cluster lpcMultiGroup contains=lpcIncluded,lpcSpecial,lpcCommentSkip,lpcCommentString,lpcComment2String,@lpcCommentGroup,lpcCommentStartError,lpcUserCont,lpcUserLabel,lpcBitField,lpcOctalZero,lpcCppOut,lpcCppOut2,lpcCppSkip,lpcFormat,lpcNumber,lpcFloat,lpcOctal,lpcOctalError,lpcNumbersCom,lpcCppParen,lpcCppBracket,lpcCppString,lpcKeywdError
|
||||
syn region lpcMulti transparent start='\(case\|default\|public\|protected\|private\)' skip='::' end=':' contains=ALLBUT,@lpcMultiGroup
|
||||
|
||||
syn cluster lpcLabelGroup contains=lpcUserLabel
|
||||
syn match lpcUserCont display "^\s*lpc:$" contains=@lpcLabelGroup
|
||||
|
||||
" Don't want to match anything
|
||||
syn match lpcUserLabel display "lpc" contained
|
||||
|
||||
" Nodule: Initializations {{{1
|
||||
|
||||
if exists("c_minlines")
|
||||
let b:c_minlines = c_minlines
|
||||
else
|
||||
if !exists("c_no_if0")
|
||||
let b:c_minlines = 50 " #if 0 constructs can be long
|
||||
else
|
||||
let b:c_minlines = 15 " mostly for () constructs
|
||||
endif
|
||||
endif
|
||||
exec "syn sync ccomment lpcComment minlines=" . b:c_minlines
|
||||
|
||||
" Make sure these options take place since we no longer depend on file type
|
||||
" plugin for C
|
||||
setlocal cindent
|
||||
setlocal fo-=t fo+=croql
|
||||
setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,://
|
||||
set cpo-=C
|
||||
|
||||
" Win32 can filter files in the browse dialog
|
||||
if has("gui_win32") && !exists("b:browsefilter")
|
||||
let b:browsefilter = "LPC Source Files (*.c *.d *.h)\t*.c;*.d;*.h\n" .
|
||||
\ "LPC Data Files (*.scr *.o *.dat)\t*.scr;*.o;*.dat\n" .
|
||||
\ "Text Documentation (*.txt)\t*.txt\n" .
|
||||
\ "All Files (*.*)\t*.*\n"
|
||||
endif
|
||||
|
||||
" Nodule: Highlight links {{{1
|
||||
|
||||
" Define the default highlighting.
|
||||
" For version 5.7 and earlier: only when not done already
|
||||
" For version 5.8 and later: only when an item doesn't have highlighting yet
|
||||
if version >= 508 || !exists("did_lpc_syn_inits")
|
||||
if version < 508
|
||||
let did_lpc_syn_inits = 1
|
||||
command -nargs=+ HiLink hi link <args>
|
||||
else
|
||||
command -nargs=+ HiLink hi def link <args>
|
||||
endif
|
||||
|
||||
HiLink lpcModifier lpcStorageClass
|
||||
|
||||
HiLink lpcQuotedFmt lpcFormat
|
||||
HiLink lpcFormat lpcSpecial
|
||||
HiLink lpcCppString lpcString " Cpp means
|
||||
" C Pre-Processor
|
||||
HiLink lpcCommentL lpcComment
|
||||
HiLink lpcCommentStart lpcComment
|
||||
HiLink lpcUserLabel lpcLabel
|
||||
HiLink lpcSpecialCharacter lpcSpecial
|
||||
HiLink lpcOctal lpcPreProc
|
||||
HiLink lpcOctalZero lpcSpecial " LPC will treat octal numbers
|
||||
" as decimals, programmers should
|
||||
" be aware of that.
|
||||
HiLink lpcEfunError lpcError
|
||||
HiLink lpcKeywdError lpcError
|
||||
HiLink lpcOctalError lpcError
|
||||
HiLink lpcParenError lpcError
|
||||
HiLink lpcErrInParen lpcError
|
||||
HiLink lpcErrInBracket lpcError
|
||||
HiLink lpcCommentError lpcError
|
||||
HiLink lpcCommentStartError lpcError
|
||||
HiLink lpcSpaceError lpcError
|
||||
HiLink lpcSpecialError lpcError
|
||||
HiLink lpcErrFunc lpcError
|
||||
|
||||
" HiLink lpcOldEfuns lpc_efuns
|
||||
HiLink lpcOldEfuns lpcReserved
|
||||
HiLink lpcNewEfuns lpcFunction
|
||||
HiLink lpcCompatEfuns lpcFunction
|
||||
HiLink lpcNativeEfuns lpcFunction
|
||||
HiLink lpcSimulEfuns lpcFunction
|
||||
HiLink lpc_efuns lpcFunction
|
||||
|
||||
HiLink lpcReserved lpcPreProc
|
||||
HiLink lpcTextString lpcString " This should be preprocessors, but
|
||||
HiLink lpcArrayString lpcPreProc " let's make some difference
|
||||
" between text and array
|
||||
|
||||
HiLink lpcIncluded lpcString
|
||||
HiLink lpcCommentString lpcString
|
||||
HiLink lpcComment2String lpcString
|
||||
HiLink lpcCommentSkip lpcComment
|
||||
HiLink lpcCommentFunc lpcComment
|
||||
|
||||
HiLink lpcCppSkip lpcCppOut
|
||||
HiLink lpcCppOut2 lpcCppOut
|
||||
HiLink lpcCppOut lpcComment
|
||||
|
||||
" Standard type below
|
||||
HiLink lpcApplies Special
|
||||
HiLink lpcCharacter Character
|
||||
HiLink lpcComment Comment
|
||||
HiLink lpcConditional Conditional
|
||||
HiLink lpcConstant Constant
|
||||
HiLink lpcDefine Macro
|
||||
HiLink lpcError Error
|
||||
HiLink lpcFloat Float
|
||||
HiLink lpcFunction Function
|
||||
HiLink lpcIdentifier Identifier
|
||||
HiLink lpcInclude Include
|
||||
HiLink lpcLabel Label
|
||||
HiLink lpcNumber Number
|
||||
HiLink lpcOperator Operator
|
||||
HiLink lpcPreCondit PreCondit
|
||||
HiLink lpcPreProc PreProc
|
||||
HiLink lpcRepeat Repeat
|
||||
HiLink lpcStatement Statement
|
||||
HiLink lpcStorageClass StorageClass
|
||||
HiLink lpcString String
|
||||
HiLink lpcStructure Structure
|
||||
HiLink lpcSpecial LineNr
|
||||
HiLink lpcTodo Todo
|
||||
HiLink lpcType Type
|
||||
|
||||
delcommand HiLink
|
||||
endif
|
||||
|
||||
" Nodule: This is the end nodule. {{{1
|
||||
|
||||
let b:current_syntax = "lpc"
|
||||
|
||||
" vim:ts=8:nosta:sw=2:ai:si:
|
||||
" vim600:set fdm=marker: }}}1
|
152
etc/lpc.xml
Normal file
152
etc/lpc.xml
Normal file
|
@ -0,0 +1,152 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "language.dtd">
|
||||
|
||||
<!--
|
||||
=============================================================================
|
||||
File: lpc.xml
|
||||
URL: http://www.metamorpher.de/files/lpc.xml
|
||||
Description: Syntax Highlighting for Lars Pensjo C (LPC)
|
||||
It is used in Multi User Dungeons which use LDMud as Gamedriver.
|
||||
For more information, see LDMud project: http://www.bearnip.com
|
||||
For best highlighting results, configure colors yourself.
|
||||
Author: Andreas Klauer (Andreas.Klauer@metamorpher.de)
|
||||
Changed: 2004-04-26
|
||||
=============================================================================
|
||||
-->
|
||||
|
||||
|
||||
<language name="LPC" version="0.72" kateversion="2.2.1"
|
||||
section="Sources" extensions="*.c;*.h;*.inc;*.o">
|
||||
|
||||
<highlighting>
|
||||
|
||||
<!-- Keyword Lists: -->
|
||||
<list name="modifiers">
|
||||
<item> private </item>
|
||||
<item> protected </item>
|
||||
<item> static </item>
|
||||
<item> public </item>
|
||||
<item> nomask </item>
|
||||
<item> varargs </item>
|
||||
<item> nosave </item>
|
||||
<item> virtual </item>
|
||||
</list>
|
||||
<list name="types">
|
||||
<item> void </item>
|
||||
<item> int </item>
|
||||
<item> status </item>
|
||||
<item> string </item>
|
||||
<item> object </item>
|
||||
<item> array </item>
|
||||
<item> mapping </item>
|
||||
<item> closure </item>
|
||||
<item> symbol </item>
|
||||
<item> float </item>
|
||||
<item> mixed </item>
|
||||
</list>
|
||||
<list name="keywords">
|
||||
<item> break </item>
|
||||
<item> continue </item>
|
||||
<item> return </item>
|
||||
<item> if </item>
|
||||
<item> else </item>
|
||||
<item> for </item>
|
||||
<item> foreach </item>
|
||||
<item> do </item>
|
||||
<item> while </item>
|
||||
<item> switch </item>
|
||||
<item> case </item>
|
||||
<item> inherit </item>
|
||||
<item> default </item>
|
||||
<item> variables </item>
|
||||
<item> functions </item>
|
||||
<item> publish </item>
|
||||
<item> nolog </item>
|
||||
</list>
|
||||
|
||||
<!-- Parsing Rules: -->
|
||||
<contexts>
|
||||
<context name="Normal" attribute="Default" lineEndContext="#stay">
|
||||
<Detect2Chars attribute="Single-Line comments" context="Comment1" char="/" char1="/" />
|
||||
<Detect2Chars attribute="Multi-Line comments" context="Comment2" char="/" char1="*" />
|
||||
<keyword String="modifiers" attribute="Modifiers" context="#stay" />
|
||||
<keyword String="types" attribute="Datatype" context="#stay" />
|
||||
<keyword String="keywords" attribute="Keywords" context="#stay" />
|
||||
<RegExpr String="^#" context="Preprocessor" attribute="Preprocessor" />
|
||||
<Float attribute="Floats" context="#stay">
|
||||
<AnyChar String="fFeE" context="#stay" />
|
||||
</Float>
|
||||
<RegExpr String="0b[01]+" attribute="Binary" context="#stay" />
|
||||
<RegExpr String="0x[0-9a-fA-F]+" attribute="Hexadecimal" context="#stay" />
|
||||
<RegExpr String="0o[0-7]+" attribute="Octal" context="#stay" />
|
||||
<Int attribute="Integer" context="#stay" />
|
||||
<RegExpr String="#'[^\t ][^\t ,);}\]/]*" attribute="Closure" context="#stay" />
|
||||
<DetectChar attribute="Strings" context="String1" char=""" />
|
||||
<HlCStringChar attribute="Char" context="#stay" />
|
||||
</context>
|
||||
<context name="Comment1" attribute="Single-Line comments" lineEndContext="#pop">
|
||||
<LineContinue attribute="Single-Line comments" context="#stay" />
|
||||
<RegExpr attribute="Comment-Keywords" context="#stay" String="^[A-Z]+:" />
|
||||
</context>
|
||||
<context name="Comment2" attribute="Multi-Line comments" lineEndContext="#stay">
|
||||
<Detect2Chars attribute="Multi-Line comments" context="#pop" char="*" char1="/"/>
|
||||
<RegExpr attribute="Comment-Keywords" context="#stay" String="^[A-Z]+:" />
|
||||
</context>
|
||||
<context name="Preprocessor" attribute="Preprocessor" lineEndContext="#pop">
|
||||
<LineContinue attribute="Preprocessor" context="#stay" />
|
||||
<Detect2Chars attribute="Single-Line comments" context="Comment1" char="/" char1="/" />
|
||||
<Detect2Chars attribute="Multi-Line comments" context="Comment2" char="/" char1="*" />
|
||||
<keyword String="modifiers" attribute="Modifier" context="#stay" />
|
||||
<keyword String="types" attribute="Datatype" context="#stay" />
|
||||
<keyword String="keywords" attribute="Keywords" context="#stay" />
|
||||
<DetectChar attribute="Preprocessor-Strings" context="String2" char=""" />
|
||||
</context>
|
||||
<context name="String1" attribute="Strings" lineEndContext="#pop">
|
||||
<LineContinue attribute="Default" context="#stay" />
|
||||
<Detect2Chars char="\" char1="\" attribute="Strings" context="#stay" />
|
||||
<Detect2Chars char="\" char1=""" attribute="Strings" context="#stay" />
|
||||
<DetectChar char=""" attribute="Strings" context="#pop" />
|
||||
</context>
|
||||
<context name="String2" attribute="Preprocessor-Strings" lineEndContext="#pop">
|
||||
<LineContinue attribute="Default" context="#stay" />
|
||||
<Detect2Chars char="\" char1="\" attribute="Preprocessor-Strings" context="#stay" />
|
||||
<Detect2Chars char="\" char1=""" attribute="Preprocessor-Strings" context="#stay" />
|
||||
<DetectChar char=""" attribute="Preprocessor-Strings" context="#pop" />
|
||||
</context>
|
||||
</contexts>
|
||||
|
||||
<!-- Color Settings: -->
|
||||
<itemDatas>
|
||||
<itemData name="Default" defStyleNum="dsNormal" />
|
||||
<itemData name="Single-Line comments" defStyleNum="dsComment" />
|
||||
<itemData name="Multi-Line comments" defStyleNum="dsComment" />
|
||||
<itemData name="Comment-Keywords" defStyleNum="dsKeyword" />
|
||||
<itemData name="Modifier" defStyleNum="dsDataType" />
|
||||
<itemData name="Datatype" defStyleNum="dsDataType" />
|
||||
<itemData name="Keywords" defStyleNum="dsKeyword" />
|
||||
<itemData name="Preprocessor" defStyleNum="dsOthers" />
|
||||
<itemData name="Floats" defStyleNum="dsFloat" />
|
||||
<itemData name="Binary" defStyleNum="dsBaseN" />
|
||||
<itemData name="Hexadecimal" defStyleNum="dsBaseN" />
|
||||
<itemData name="Octal" defStyleNum="dsBaseN" />
|
||||
<itemData name="Integer" defStyleNum="dsDecVal" />
|
||||
<itemData name="Closure" defStyleNum="dsOthers" />
|
||||
<itemData name="Strings" defStyleNum="dsString" />
|
||||
<itemData name="Preprocessor-Strings" defStyleNum="dsString" />
|
||||
<itemData name="Char" defStyleNum="dsChar" />
|
||||
</itemDatas>
|
||||
</highlighting>
|
||||
|
||||
<!-- This is not for highlighting, but for detecting comments.
|
||||
It allows Kate to hide comments if the user wished to do so. -->
|
||||
<general>
|
||||
<comments>
|
||||
<comment name="singleLine" start="//" />
|
||||
<comment name="multiLine" start="/*" end="*/" />
|
||||
</comments>
|
||||
<keywords casesensitive="1" />
|
||||
</general>
|
||||
|
||||
</language>
|
||||
|
||||
<!-- === End of file. === -->
|
96
etc/memusage
Executable file
96
etc/memusage
Executable file
|
@ -0,0 +1,96 @@
|
|||
#!/usr/bin/perl -w
|
||||
# originating from MorgenGrauen
|
||||
# 11.06.02 Fiona more robust parsing
|
||||
|
||||
$MUDLIBDIR = "/usr/mud/mudlib/";
|
||||
$HOMES = "players";
|
||||
$DOMAINS = "d";
|
||||
$OUTPUTDIR = $MUDLIBDIR."tmp/";
|
||||
|
||||
$| = 1;
|
||||
printf("Creating Object-Lists ... ");
|
||||
%mem=(); %inst=(); %envs=(); %TotalMem=(); $MemSum=0;
|
||||
%wizobj=();%wizmem=();%domobj=();%dommem=();
|
||||
open(DUMP,$MUDLIBDIR."OBJ_DUMP");
|
||||
|
||||
for (<DUMP>)
|
||||
{
|
||||
chop;
|
||||
#@line=split(' ');
|
||||
print("matcherr: $_\n")
|
||||
unless $_ =~ /^([^ ]+) \D*(\d+)\D*(\d+)\D*\d+ +(HB)? +(\S*)/;
|
||||
$env=$5;
|
||||
$env.=' *HB*' if ($4);
|
||||
@fname=split('#',$1);
|
||||
$mem{$1}=$2;
|
||||
$inst{$fname[0]}+=1;
|
||||
$TotalMem{$fname[0]}+=$2;
|
||||
$envs{$1}=$5;
|
||||
$MemSum+=$2;
|
||||
@path=split("/",$1);
|
||||
if ($path[0] eq $HOMES)
|
||||
{
|
||||
$wizobj{$path[1]}++;
|
||||
$wizmem{$path[1]}+=$2;
|
||||
}
|
||||
if ($path[0] eq $DOMAINS)
|
||||
{
|
||||
$wizobj{$path[2]}++;
|
||||
$wizmem{$path[2]}+=$2;
|
||||
$domobj{$path[1]}++;
|
||||
$dommem{$path[1]}+=$2;
|
||||
}
|
||||
}
|
||||
|
||||
printf("done\nMEMORY list is being created ... sorting ... ");
|
||||
@keys=sort {$mem{$b} <=> $mem{$a}} keys %mem;
|
||||
|
||||
print "dumping ... ";
|
||||
open(DUMP,">".$OUTPUTDIR."MEMORY_SORTED");
|
||||
printf DUMP "Memory usage according to OBJ_DUMP is %d bytes.\n",$MemSum;
|
||||
foreach $key (@keys)
|
||||
{
|
||||
printf DUMP "%-30s: mem=%4d, env=%s\n", $key, $mem{$key}, $envs{$key};
|
||||
}
|
||||
close(DUMP);
|
||||
|
||||
printf("done\nCOUNT_LIST is being created ... sorting ... ");
|
||||
@keys=sort {$inst{$b} <=> $inst{$a}} keys %inst;
|
||||
|
||||
print "dumping ... ";
|
||||
open(DUMP,">".$OUTPUTDIR."COUNT_SORTED");
|
||||
foreach $key (@keys)
|
||||
{
|
||||
printf DUMP "%3d instances using %4d Bytes: %s\n",$inst{$key},$TotalMem{$key},$key;
|
||||
}
|
||||
close(DUMP);
|
||||
|
||||
printf("done\nTOTAL_MEM_LIST is being created ... sorting ... ");
|
||||
@keys=sort {$TotalMem{$b} <=> $TotalMem{$a}} keys %inst;
|
||||
|
||||
print "dumping ... ";
|
||||
open(DUMP,">".$OUTPUTDIR."TOTAL_MEM");
|
||||
foreach $key (@keys)
|
||||
{
|
||||
printf DUMP "%3d instances using %4d Bytes: %s\n",$inst{$key},$TotalMem{$key},$key;
|
||||
}
|
||||
close(DUMP);
|
||||
|
||||
printf("done\nDumping OWNER list ... ");
|
||||
@keys=sort {$wizmem{$b} <=> $wizmem{$a}} keys %wizmem;
|
||||
|
||||
open(DUMP,">".$OUTPUTDIR."BY_NAME");
|
||||
printf DUMP "How much Memory does each Wizard use ?\n";
|
||||
foreach $key (@keys)
|
||||
{
|
||||
printf DUMP "%-14s: %4d objects using %9d bytes\n", $key,$wizobj{$key},$wizmem{$key};
|
||||
}
|
||||
printf DUMP "\n\nHow much Memory does each domain use ?\n";
|
||||
@keys=sort {$dommem{$b} <=> $dommem{$a}} keys %dommem;
|
||||
foreach $key (@keys)
|
||||
{
|
||||
printf DUMP "%-14s: %4d objects using %9d bytes\n", $key,$domobj{$key},$dommem{$key};
|
||||
}
|
||||
close(DUMP);
|
||||
|
||||
print "done\n";
|
94
etc/psyclpc.ebuild
Normal file
94
etc/psyclpc.ebuild
Normal file
|
@ -0,0 +1,94 @@
|
|||
# Copyright 1999-2006 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: /CVS/anonCVS/psyclpc/etc/psyclpc.ebuild,v 1.1 2007/08/14 09:03:30 lynx Exp $
|
||||
#
|
||||
# psyclpc is a programming language for intense multi-user network applications
|
||||
# such as psyced. it's a recent fork of LDMUD with some features and many
|
||||
# bug fixes. we kept it compatible to LDMUD, so you can run a MUD with it, too.
|
||||
#
|
||||
# Suggestions? tell psyc://psyced.org/~lynX
|
||||
#
|
||||
# WARNING/REMINDER to myself: When checking in a new version of this file
|
||||
# into CVS I have to run 'make up' in the gentoo download tar, as it also
|
||||
# relinks all the psyclpc/psyclpc-VERSION.ebuild files. 'cvs update' alone
|
||||
# wouldn't do that.
|
||||
#
|
||||
# this ebuild file is available in both psyclpc/etc and psyced/config/gentoo.
|
||||
# psyced also provides installation automations.
|
||||
|
||||
inherit toolchain-funcs eutils
|
||||
|
||||
DESCRIPTION="psycLPC is a multi-user network server programming language"
|
||||
HOMEPAGE="http://lpc.psyc.eu/
|
||||
|
||||
# using the filename of the ebuild here!
|
||||
# so better give it numbers which are actually
|
||||
# available in http://www.psyced.org/files/
|
||||
SRC_URI="http://www.psyced.org/files/${P}.tar.bz2"
|
||||
|
||||
LICENSE="GPL-2"
|
||||
SLOT="0"
|
||||
# haven't checked for real..
|
||||
# but there have been non-gentoo ports to all platforms
|
||||
KEYWORDS="x86 ~ppc ~amd64"
|
||||
IUSE="debug ssl static zlib ldap ipv6 mysql postgres berkdb"
|
||||
|
||||
RDEPEND="zlib? ( sys-libs/zlib )
|
||||
ssl? ( dev-libs/openssl )
|
||||
ldap? ( net-nds/openldap )
|
||||
berkdb? ( sys-libs/db )
|
||||
mysql? ( dev-db/mysql )
|
||||
postgres? ( dev-db/postgresql )"
|
||||
|
||||
DEPEND="${RDEPEND}
|
||||
>=sys-devel/flex-2.5.4a-r5
|
||||
>=sys-devel/bison-1.875
|
||||
>=sys-devel/gettext-0.12.1"
|
||||
|
||||
#MYS="/var/tmp/portage/${P}/work/${P}/src"
|
||||
MYS="${S}/src"
|
||||
|
||||
src_compile() {
|
||||
cd "${MYS}"
|
||||
# use berkdb >&/dev/null && myopts="${myopts} --enable-db"
|
||||
# use mysql >&/dev/null && myopts="${myopts} --enable-mysql" || myopts="${myopts} --disable-mysql"
|
||||
# use postgres >&/dev/null && myopts="${myopts} --enable-pgsql"
|
||||
# use ldap >&/dev/null && myopts="${myopts} --enable-ldap"
|
||||
# use ipv6 >&/dev/null && myopts="${myopts} --enable-ipv6"
|
||||
use zlib && {
|
||||
einfo "Compiling ${P} with zlib (MCCP) support."
|
||||
myopts="${myopts} --enable-use-mccp"
|
||||
}
|
||||
use ssl && {
|
||||
einfo "Compiling ${P} with SSL support."
|
||||
myopts="${myopts} --enable-use-tls=yes"
|
||||
}
|
||||
use mysql && {
|
||||
einfo "Compiling ${P} with mySQL support."
|
||||
myopts="${myopts} --enable-use-mysql"
|
||||
}
|
||||
use postgres && {
|
||||
einfo "Compiling ${P} with PostgreSQL support."
|
||||
myopts="${myopts} --enable-use-pgsql"
|
||||
}
|
||||
use debug && {
|
||||
append-flags -O -ggdb -DDEBUG
|
||||
RESTRICT="${RESTRICT} nostrip"
|
||||
myopts="${myopts} --enable-debug"
|
||||
}
|
||||
# runs configure
|
||||
echo ${myopts}
|
||||
# choice of settings should be configurable.. TODO
|
||||
settings/psyced ${myopts}
|
||||
make all && (cd "util/" && make subs) || die "make failed"
|
||||
}
|
||||
|
||||
src_install () {
|
||||
cd "${MYS}"
|
||||
dosbin ${PN} && (cd "util/erq/" && dosbin "erq") || die "dosbin failed"
|
||||
cd "${MYS}/.."
|
||||
# only the interesting files
|
||||
dodoc HELP CHANGELOG psyclpc.1
|
||||
# maybe we should install etc/lpc.vim?
|
||||
# and what about the man file?
|
||||
}
|
209
etc/savefile-parse.pl
Normal file
209
etc/savefile-parse.pl
Normal file
|
@ -0,0 +1,209 @@
|
|||
#!/usr/bin/perl -w
|
||||
######
|
||||
#
|
||||
# Parse a mudmode (save_value) string
|
||||
#
|
||||
# A single variable value is parsed and represented as perl data structure.
|
||||
# So a string like '({"a",3,(["b":2,]),})' gets ['a',3,{'b'=>2}]
|
||||
#
|
||||
# Fiona 23-Mai-03
|
||||
#
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
$parse_err = undef; # Global error messages
|
||||
|
||||
%unquote = (
|
||||
'r' => "\r",
|
||||
'f' => "\f",
|
||||
'v' => "\v",
|
||||
'n' => "\n",
|
||||
't' => "\t",
|
||||
'b' => "\b",
|
||||
'a' => "\a",
|
||||
);
|
||||
|
||||
# parse a single value
|
||||
#
|
||||
# Knows: int, string, array, float, mapping
|
||||
# (Todo: ref_to_array/mapping, closures)
|
||||
#
|
||||
# arguments: source string
|
||||
# reference to start index of value
|
||||
# returns value in perl
|
||||
# set start index to next char (if any) or -1
|
||||
#
|
||||
# If an error occured -1 will be returned and $parse_err set
|
||||
|
||||
sub get_value {
|
||||
my ($offsp, $str, $ret, $ret2, $data);
|
||||
$str = $_[0];
|
||||
$offsp = $_[1];
|
||||
|
||||
# check for float
|
||||
#
|
||||
# [German:Koresh@OuterSpace] OS would encode it as #-1.00000001e-01# but
|
||||
# not sure everybody does it this way.
|
||||
# [German:Fiona] means ({-0.1}) becomes ({#-1.00000001e-01#,}) ?
|
||||
# [German] Koresh@OuterSpace nods wildly
|
||||
# [German] Koresh@OuterSpace also notes that mudos does not seem to include
|
||||
# the # in floats: it just writes it as ({-1.00000e-08,})
|
||||
#
|
||||
# LDmud float
|
||||
# -9.999999997672e-02=fffd:9999999a
|
||||
|
||||
pos($str) = $$offsp;
|
||||
$str =~ m/\G#?(-?\d.\d*[eE][-+]\d\d)(#|=[0-9a-f:]+)?/sg;
|
||||
if (defined $1) {
|
||||
$$offsp = pos($str);
|
||||
return $1;
|
||||
}
|
||||
|
||||
# check for int (check *after* floats)
|
||||
pos($str) = $$offsp;
|
||||
$str =~ m/\G(-?\d+)/sg;
|
||||
if (defined $1) {
|
||||
$$offsp = pos($str);
|
||||
return $1;
|
||||
}
|
||||
|
||||
# check for string
|
||||
pos($str) = $$offsp;
|
||||
if ($str =~ m/\G"((?:[^"\\]+|\\.)*)"/sg ) {
|
||||
$$offsp = pos($str);
|
||||
# unquote string
|
||||
$ret = $1;
|
||||
$ret =~ s/\\(.)/$unquote{$1}||$1/esg;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# check for array
|
||||
pos($str) = $$offsp;
|
||||
if ($str =~ m/\G\({/sg ) {
|
||||
$$offsp = pos($str);
|
||||
$data = [];
|
||||
|
||||
if ($str =~ m/\G}\)/sg ) {
|
||||
$$offsp += 2;
|
||||
return $data;
|
||||
}
|
||||
|
||||
# recurse array
|
||||
while (1) {
|
||||
$ret = get_value($str, $offsp);
|
||||
return -1 if ($parse_err || $offsp == -1);
|
||||
|
||||
push @{$data}, $ret;
|
||||
|
||||
pos($str) = $$offsp;
|
||||
if (not ($str =~ m/\G,/sg )) {
|
||||
pos($str) = $$offsp;
|
||||
$str =~ m/\G(.{0,8})/sg;
|
||||
$parse_err = "Comma missing in array near '$1'";
|
||||
return -1;
|
||||
}
|
||||
$$offsp += 1;
|
||||
|
||||
if ($str =~ m/\G}\)/sg ) {
|
||||
$$offsp += 2;
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
# notreached
|
||||
}
|
||||
|
||||
# check for mapping
|
||||
#
|
||||
# MudOS has no 2dimensional Mappings, so we dont support them
|
||||
# (perl is unable to represent them anyhow)
|
||||
# Zero-width mappings are impossible with mudmode/perl, so emulate them.
|
||||
|
||||
pos($str) = $$offsp;
|
||||
if ($str =~ m/\G\(\[/sg ) {
|
||||
$$offsp = pos($str);
|
||||
$data = {};
|
||||
|
||||
if ($str =~ m/\G]\)/sg ) {
|
||||
$$offsp += 2;
|
||||
return $data;
|
||||
}
|
||||
|
||||
# recurse array
|
||||
while (1) {
|
||||
$ret = get_value($str, $offsp);
|
||||
return -1 if ($parse_err || $offsp == -1);
|
||||
|
||||
|
||||
pos($str) = $$offsp;
|
||||
if (not ($str =~ m/\G[:,]/sg )) {
|
||||
pos($str) = $$offsp;
|
||||
if ($str =~ m/\G;/sg ) {
|
||||
$parse_err = 'Multidimensional mapping not supported near ';
|
||||
} else {
|
||||
$parse_err = 'Colon missing in mapping near ';
|
||||
}
|
||||
pos($str) = $$offsp;
|
||||
$str =~ m/\G(.{0,8})/sg;
|
||||
$parse_err = $parse_err . "'$1'";
|
||||
return -1;
|
||||
}
|
||||
$$offsp += 1;
|
||||
|
||||
pos($str) = $$offsp-1;
|
||||
if ($str =~ m/\G,/sg ) { # zero width, gets simulated...
|
||||
$ret2 = 0;
|
||||
} else {
|
||||
$ret2 = get_value($str, $offsp);
|
||||
return -1 if ($parse_err || $offsp == -1);
|
||||
|
||||
pos($str) = $$offsp;
|
||||
|
||||
if (not ($str =~ m/\G,/sg )) {
|
||||
pos($str) = $$offsp;
|
||||
$str =~ m/\G(.{0,8})/sg;
|
||||
$parse_err = "Comma missing in mapping near '$1'";
|
||||
return -1;
|
||||
}
|
||||
$$offsp += 1;
|
||||
}
|
||||
|
||||
$$data{$ret} = $ret2;
|
||||
|
||||
if ($str =~ m/\G]\)/sg ) {
|
||||
$$offsp += 2;
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
# notreached
|
||||
}
|
||||
|
||||
# check for parse error
|
||||
pos($str) = $$offsp;
|
||||
$str =~ m/\G(.{1,8})/sg;
|
||||
if (defined $1) {
|
||||
$parse_err = "Unknown variable type near '$1'";
|
||||
return -1;
|
||||
}
|
||||
|
||||
# end of string
|
||||
$$offsp = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
######
|
||||
#
|
||||
# Sample usage
|
||||
#
|
||||
|
||||
$str = '({1234,45,({12,-1,({0,}),}),"fla\nb\"ber",-1.110999999642e+02=7:90e66667,({}),(["b":"a","c":({1,-2,}),]),([1,2,3,]),})';
|
||||
|
||||
#$str='({"error",5,"*gjs",0,"Test-PerlMud-i3",0,"unk-src","router does not know you",({"startup-req-3",5,"Test-PerlMud-i3",0,"",0,1016,4156424,330,0,0,0,"PerlLib v1","PerlLib v1","Perlv5.6.1","Perl","restricted access","castaway@desert-island.m.isar.de",(["channel":1,"nntp":0,"file":0,"amcp":0,"rcp":0,"emoteto":1,"auth":0,"who":1,"smtp":0,"mail":0,"finger":1,"ucache":1,"locate":1,"news":0,"http":0,"ftp":0,"tell":1,]),0,}),})';
|
||||
|
||||
$posi = 0;
|
||||
$ret = get_value($str, \$posi);
|
||||
|
||||
if ($parse_err) {
|
||||
print("ERROR $parse_err\n");
|
||||
} else {
|
||||
print(Dumper($ret));
|
||||
}
|
80
mudlib/ACCESS.ALLOW
Normal file
80
mudlib/ACCESS.ALLOW
Normal file
|
@ -0,0 +1,80 @@
|
|||
# ACCESS.ALLOW - Game access allowance rules
|
||||
#----------------------------------------------------------------------------
|
||||
# Access to the game is based on the user's IP address and the current time.
|
||||
# These are matched against a set of rules and if a match is detected, a
|
||||
# proper message is sent back and the connection is shutdown.
|
||||
#
|
||||
# This facility is active only if ACCESS_CONTROL has been defined in config.h
|
||||
# If ACCESS_LOG is defined in config.h, all checks and their results are
|
||||
# logged in the specified file.
|
||||
#
|
||||
# The rules are read from the file ACCESS_FILE (defined in config.h,
|
||||
# typically "ACCESS.ALLOW" with a name relative to the mudlib directory).
|
||||
# Every line specifies one rule and has to follow the syntax given below.
|
||||
# Lines with a '#' as first character count as comments and are ignored, as
|
||||
# are lines which do not conform to the rule syntax (but except for empty
|
||||
# lines this should be relied upon).
|
||||
#
|
||||
# The rule file is (re)read whenever the gamedriver detects a change in its
|
||||
# timestamp.
|
||||
#
|
||||
# The syntax for a rule is (no leading whitespace allowed!):
|
||||
#
|
||||
# <ipnum>:[p<port>]:<class>:<max>:<start>:<end>:<text>
|
||||
# <ipnum>:[p<port>]:<class>:<max>:h<hours>:w<days>:m=<text>
|
||||
#
|
||||
# where
|
||||
# ipnum: <byte>.<byte>.<byte>.<byte>, with byte = * or number
|
||||
# There is only loose error checking - specifying an illegal
|
||||
# address will have interesting consequences, but would
|
||||
# most likely cause no error to occur.
|
||||
# port: the port number to which the connection is made. Omission
|
||||
# means 'any port'.
|
||||
# class: number
|
||||
# max: the maximum number of users, a number. The value -1 allows
|
||||
# an unlimited number of users.
|
||||
# start: hour this rule starts to be valid (0..23).
|
||||
# end: hour this rule ceases to be valid (0..23).
|
||||
# Setting both start and end to 0 skips any time check.
|
||||
# hours: hours this rule is valid.
|
||||
# This form allows several entries, separated with a ','.
|
||||
# Every entry can be a single hour (0..23), or a range in the
|
||||
# form '<start>-<end>'
|
||||
# Omitting the entry skips any time check.
|
||||
# days: the days this rule is valid.
|
||||
# The syntax is similar to <hours> except for the
|
||||
# allowable values: the days Sunday..Saturday are given as
|
||||
# the numbers 0..6.
|
||||
# Omitting the entry skips any day check.
|
||||
# text: string to send if the rule matches.
|
||||
#
|
||||
# A class is defined by the first rule using it's number. This
|
||||
# definition specifies the allowable <max>imum of users and the <text>
|
||||
# to send. Subsequent rules for the same class just add new ipnumber/
|
||||
# time rules, but don't change <max> or <text>
|
||||
#
|
||||
# ORDER MATTERS. That means if you allow 129.*.*.*, you have to put
|
||||
# any restrictions on 129.132.*.* BEFORE this rule.
|
||||
#
|
||||
# Addresses not matching any rule at all are not allowed to connect. To get
|
||||
# around this, add an appropriate 'allow-all' rule *.*.*.* at the very end.
|
||||
#
|
||||
# A typical rulefile would look like this one:
|
||||
|
||||
# SPARC cluster has access denied. Class 1
|
||||
129.132.122.*:1:0:0:0:LPMUD access denied for your cluster.
|
||||
|
||||
# CALL-1A0 has access limited to some maximum, for now 5 logins. Class 2
|
||||
129.132.106.*:2:5:8:20:Sorry, LPMUD is currently full.
|
||||
|
||||
# CALL-1A0 at all other times, its a 10 limit.
|
||||
# Due to the rule order, this is effectively limited to times
|
||||
# outside 8-20.
|
||||
129.132.106.*:3:10:0:0:Sorry, LPMUD is currently full.
|
||||
|
||||
# No more than 5 users allowed from localhost while working hours :-)
|
||||
127.0.0.1:42:5:h8-12,13-18:w1-5:m=Pick a better time.
|
||||
|
||||
# Everybody else is welcome.
|
||||
*.*.*.*:0:-1:0:0:This message should never be printed.
|
||||
|
22
mudlib/README
Normal file
22
mudlib/README
Normal file
|
@ -0,0 +1,22 @@
|
|||
This directory holds various example and support files for mudlibs.
|
||||
Especially important is the sys/ subdirectory with the driver-related
|
||||
include files.
|
||||
|
||||
Other files are:
|
||||
|
||||
ACCESS.ALLOW : a typical access control file.
|
||||
master_skeleton.c: a skeleton master, documenting all master lfuns.
|
||||
telnet.h, telnetneg.c: the Wunderland telnet module, a complete implementation
|
||||
of the telnet protocol.
|
||||
test_master.c : a minimal test master for driver tests.
|
||||
simul_efun-dr.c : a very old simul_efun file for a very old DR mudlib.
|
||||
erq-tool.c : for 2.4.5 muds, a tool for interactive erq experiments.
|
||||
dhrystone.c : an implementation of Dhrystone, called by the
|
||||
test_master.
|
||||
astar.c : an implementation of the A* pathfinding algorithm.
|
||||
pgsql.c : example for using PostgreSQL
|
||||
dns_resolve.c : a simul-efun for non-block DNS lookups
|
||||
query_ip_name.c : a simul-efun for IPv4/IPv6 name lookups
|
||||
|
||||
uni-crasher/ : A stress test program, see the README in this dir.
|
||||
|
196
mudlib/astar.c
Normal file
196
mudlib/astar.c
Normal file
|
@ -0,0 +1,196 @@
|
|||
#if 0
|
||||
--------------------------------------------------------------------------
|
||||
Date: Thu, 13 Dec 2001 00:34:12 -0700
|
||||
From: Acius <helpsfamily@attbi.com>
|
||||
|
||||
A while back we were talking about eventually putting path-finding in
|
||||
the driver, but I don't know if anyone came up with anything really
|
||||
specific (I might add that I've been off the mailing list for a little
|
||||
while now, thanks to @Home's problems). I wanted path-finding for my
|
||||
MUD, and since it sounded like it might be a while until Lars has enough
|
||||
time to play with it, I've implemented A-star in LP/C. The code is
|
||||
attached to this message.
|
||||
|
||||
I have a couple reasons for posting the code: Firstly, anyone who might
|
||||
want to use it can try it, and if they post their modifications and
|
||||
bugfixes, I get better code for free :-). Also, it serves as an
|
||||
interface and behavior suggestion for future code to be put into the
|
||||
driver. I wrote it with this idea in mind, and I have attempted to make
|
||||
the code a very general way to do 2d path-finding. The code could be
|
||||
placed in a simul_efun for now, and simply commented out or removed when
|
||||
and if driver path-finding code comes on line.
|
||||
|
||||
The parameters are:
|
||||
|
||||
* A string, giving the map on which you're doing the search
|
||||
* The x, y of the starting location
|
||||
* The x, y of the goal location
|
||||
* A mapping of ([ character: cost ]) for all of the characters used in
|
||||
the map string. All characters not included in the mapping are assumed
|
||||
to be walls. A cost of 0 might not get the best path if you use it,
|
||||
since Manhattan distance is used to guide the search and it will
|
||||
overestimate (go read a good article on A-star).
|
||||
|
||||
Here's a quick example of how to use it:
|
||||
|
||||
.*.#.
|
||||
.#...
|
||||
...
|
||||
|
||||
I want to get from the upper left corner (0, 0) to the upper right
|
||||
corner (4, 0), and I need to know the path to get there. The #'s are
|
||||
walls, and may not be crossed. The '*' may be crossed, but it is a
|
||||
"poisonous" tile and should not be crossed if there is an alternative.
|
||||
Note that the grid doesn't have to be square; the function will append
|
||||
each line with "\27"'s to make it square.
|
||||
|
||||
Here's how to make a function call to get this path:
|
||||
|
||||
string path;
|
||||
path =
|
||||
find_path(".*.#.\n.#...\n...", 0, 0, 4, 0, ([ '.': 1, '*': 100 ]));
|
||||
if( path )
|
||||
write("You should go "+path+"\n");
|
||||
else
|
||||
write("No path could be found.\n");
|
||||
|
||||
On my MUD, the call to find_path returns the string "sseeneen". If you
|
||||
lower the cost of '*' to 5 (just change the 100 to a 5), then it returns
|
||||
the string "eeseen".
|
||||
|
||||
If there are any other questions, please email me; this message is
|
||||
getting long enough already. I particularly want to hear from you if you
|
||||
get it working (or can't!) and if you find bugs or ways to make it more
|
||||
efficient (it is not very efficient). I tried not to put in anything
|
||||
MUDlib-specific, but sometimes I forget.
|
||||
|
||||
-- Acius
|
||||
--------------------------------------------------------------------------
|
||||
#endif
|
||||
|
||||
string find_path( string map, int startx, int starty, int goalx, int goaly, mapping costs ) {
|
||||
// split_map will be an array of equal-length
|
||||
//strings (will pad spaces to assure this)
|
||||
string *split_map;
|
||||
|
||||
// i is for generic loops, map_width is width
|
||||
// of split_map, goal is the destination point
|
||||
// (All coordinates are stored as x + y *
|
||||
// width). currpos is where the algorithm is
|
||||
// looking, currcost is cost at currpos, newx,
|
||||
// newy, newpos, and newcost are temps for
|
||||
// figuring out where to look next.
|
||||
int i, map_width, start, goal, currpos, currcost, newx, newy, newpos, newcost;
|
||||
int ineighbor, iparent, iheap;
|
||||
|
||||
// closed is mapping from (int)coordinate:
|
||||
// (int) cost & direction. Note that costs
|
||||
// > 2^28 will cause undetected overflow
|
||||
// problems -- if you keep costs reasonable,
|
||||
// you shouldn't have a problem.
|
||||
mapping closed;
|
||||
|
||||
// The open list, stored as a heap.
|
||||
// Even-numbered elements hold coordinate information,
|
||||
// odd-numbered ones give the cost for the previous
|
||||
// even numbered coordinate.
|
||||
int *open;
|
||||
string path;
|
||||
|
||||
mixed tmp;
|
||||
|
||||
// Process the map into an easier-to-use format.
|
||||
split_map = explode( map, "\n" );
|
||||
map_width = 0;
|
||||
|
||||
// Find the length of the longest line in the "map"
|
||||
for( i = sizeof(split_map); i-- ; )
|
||||
if( map_width < strlen(split_map[i]) ) map_width = strlen(split_map[i]);
|
||||
|
||||
// Make all the lines that length by padding with escape characters.
|
||||
// (Note: I use escapes because they are an unlikely character to be
|
||||
// chosen for walking over, and unused characters are 'walls')
|
||||
for( i = sizeof(split_map); i-- ; )
|
||||
split_map[i] += sprintf( "%" + (map_width-strlen(split_map[i])) + "'\27's", "" );
|
||||
|
||||
// Sanity check
|
||||
if( goalx < 0 || goalx >= map_width || goaly < 0 || goaly >= sizeof(split_map) )
|
||||
return 0;
|
||||
// Setup initial state.
|
||||
start = startx + starty * map_width;
|
||||
goal = goalx + goaly * map_width;
|
||||
open = ({ 0, start });
|
||||
closed = ([ start:0 ]);
|
||||
|
||||
while( sizeof(open) && !member(closed, goal) ) {
|
||||
currcost = open[0];
|
||||
currpos = open[1];
|
||||
// Check if done.
|
||||
if( currpos == goal ) {
|
||||
closed[currpos] = currcost;
|
||||
break;
|
||||
}
|
||||
|
||||
// Pop the top cell off the heap.
|
||||
open[0] = open[<2];
|
||||
open[1] = open[<1];
|
||||
open = open[0..<3];
|
||||
iparent = 0;
|
||||
iheap = 2;
|
||||
while( iheap < sizeof(open) ) {
|
||||
if( open[iparent] > open[iheap] && (iheap + 2 >= sizeof(open) || open[iheap] < open[iheap + 2]) ) {
|
||||
tmp = open[iparent..iparent+1];
|
||||
open[iparent..iparent + 1] = open[iheap..iheap + 1];
|
||||
open[iheap..iheap + 1] = tmp;
|
||||
}
|
||||
else if( iheap + 2 < sizeof(open) && open[iparent] > open[iheap + 2] ) {
|
||||
tmp = open[iparent..iparent+1];
|
||||
open[iparent..iparent + 1] = open[iheap + 2..iheap + 3];
|
||||
open[iheap + 2..iheap + 3] = tmp;
|
||||
}
|
||||
else
|
||||
break;
|
||||
iparent = iheap;
|
||||
iheap = (iparent + 1) << 1;
|
||||
}
|
||||
|
||||
// Add the neighbors of the popped cell to the heap
|
||||
// 0 = east, 1 = north, 2 = west, 3 = south
|
||||
for( ineighbor = 0; ineighbor < 4; ineighbor++ ) {
|
||||
newx = (currpos % map_width) + ({ 1, 0, -1, 0 })[ineighbor];
|
||||
newy = (currpos / map_width) + ({ 0, -1, 0, 1 })[ineighbor];
|
||||
newcost = ({ 0x0, 0x1, 0x2, 0x3 })[ineighbor];
|
||||
// Out of bounds, ignore it.
|
||||
if( newx < 0 || newx >= map_width || newy < 0 || newy >= sizeof(split_map) )
|
||||
continue;
|
||||
// Solid wall, ignore it.
|
||||
if( !member(costs, split_map[newy][newx]) ) continue;
|
||||
newpos = newx + newy * map_width;
|
||||
// Already checked, ignore it.
|
||||
if( member(closed, newpos) ) continue;
|
||||
// Ok, it's legit. Add it to the heap:
|
||||
newcost |= (currcost & 0xFFFC) + (costs[split_map[newy][newx]] << 2);
|
||||
newcost -= (abs(currpos % map_width) + abs(currpos / map_width)) << 2;
|
||||
newcost += (abs(goalx - newx) + abs(goaly - newy)) << 2;
|
||||
// Mark this cell as 'considered'
|
||||
closed[newpos] = newcost;
|
||||
iheap = sizeof(open);
|
||||
open += ({ newcost, newpos });
|
||||
if( iheap > 0 )
|
||||
while( open[iparent = ((iheap >> 1) - 1) & -2] > open[iheap] ) {
|
||||
tmp = open[iparent..iparent+1];
|
||||
open[iparent..iparent+1] = open[iheap..iheap+1];
|
||||
open[iheap..iheap+1] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
i = goal;
|
||||
if( !member(closed, i) ) return 0;
|
||||
path = "";
|
||||
while( i != start ) {
|
||||
path = ({ "e", "n", "w", "s" })[closed[i]&0x3] + path;
|
||||
i += ({ -1, map_width, 1, -map_width })[closed[i]&0x3];
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
365
mudlib/dhrystone.c
Normal file
365
mudlib/dhrystone.c
Normal file
|
@ -0,0 +1,365 @@
|
|||
//===========================================================================
|
||||
// Dhrystone-2.1 Benchmark for LPC
|
||||
//
|
||||
// Don't take this too serious :-) Sven C. Dack
|
||||
//===========================================================================
|
||||
|
||||
#define Default_Number_Of_Runs 10000
|
||||
|
||||
#pragma strong_types
|
||||
|
||||
//===========================================================================
|
||||
// Support functions to simulate memory allocation and other stuff..
|
||||
|
||||
mixed *alloc_array_50() { return allocate(50); }
|
||||
|
||||
mixed *alloc_array_50_50() {
|
||||
mixed *arr;
|
||||
int i;
|
||||
|
||||
for (i = 50, arr = allocate(50); i--; arr[i] = allocate(50));
|
||||
return arr;
|
||||
}
|
||||
|
||||
mapping alloc_record() {
|
||||
return ([ "Ptr_Comp": 0, "Discr": 0, "var_1": ({ 0, 0, "" }) ]);
|
||||
}
|
||||
|
||||
mapping copy_record(mapping rec) {
|
||||
mapping r;
|
||||
|
||||
r = copy(rec);
|
||||
r["var_1"] = ({}) + rec["var_1"];
|
||||
return r;
|
||||
}
|
||||
|
||||
int times() {
|
||||
int *ru;
|
||||
|
||||
ru = rusage();
|
||||
return ru[0] + ru[1];
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// The global variables.
|
||||
|
||||
#define Ident_1 0
|
||||
#define Ident_2 1
|
||||
#define Ident_3 2
|
||||
#define Ident_4 3
|
||||
#define Ident_5 4
|
||||
|
||||
#define Enum_Comp 0
|
||||
#define Int_Comp 1
|
||||
#define Str_Comp 2
|
||||
|
||||
mapping Ptr_Glob, Next_Ptr_Glob;
|
||||
int Int_Glob;
|
||||
int Bool_Glob;
|
||||
int Ch_1_Glob, Ch_2_Glob;
|
||||
mixed *Arr_1_Glob;
|
||||
mixed *Arr_2_Glob;
|
||||
int Begin_Time, End_Time, User_Time;
|
||||
float Milliseconds, Dhrystones_Per_Second;
|
||||
|
||||
//===========================================================================
|
||||
// Prototypes all functions (including those defined later).
|
||||
|
||||
void Proc_1(mapping m1);
|
||||
void Proc_2(int i1);
|
||||
void Proc_3(mapping m1);
|
||||
void Proc_4();
|
||||
void Proc_5();
|
||||
void Proc_6(int i1, int i2);
|
||||
void Proc_7(int i1, int i2, int i3);
|
||||
void Proc_8(mixed *a1, mixed *a2, int i1, int i2);
|
||||
int Func_1(int i1, int i2);
|
||||
int Func_2(string s1, string s2);
|
||||
int Func_3(int i1);
|
||||
|
||||
//===========================================================================
|
||||
|
||||
float main(int Number_Of_Runs, int silent) {
|
||||
int Int_1_Loc, Int_2_Loc, Int_3_Loc;
|
||||
int Ch_Index;
|
||||
int Enum_Loc;
|
||||
string Str_1_Loc, Str_2_Loc;
|
||||
int Run_Index;
|
||||
|
||||
if (Number_Of_Runs <= 0)
|
||||
Number_Of_Runs = Default_Number_Of_Runs;
|
||||
|
||||
Arr_1_Glob = alloc_array_50();
|
||||
Arr_2_Glob = alloc_array_50_50();
|
||||
Str_1_Loc = "";
|
||||
Str_2_Loc = "";
|
||||
Next_Ptr_Glob = alloc_record();
|
||||
Ptr_Glob = alloc_record();
|
||||
Ptr_Glob["Ptr_Comp"] = Next_Ptr_Glob;
|
||||
Ptr_Glob["Discr"] = Ident_1;
|
||||
Ptr_Glob["var_1"][Enum_Comp] = Ident_3;
|
||||
Ptr_Glob["var_1"][Int_Comp] = 40;
|
||||
Ptr_Glob["var_1"][Str_Comp] = "DHRYSTONE PROGRAM, SOME STRING";
|
||||
Str_1_Loc = "DHRYSTONE PROGRAM, 1'ST STRING";
|
||||
Arr_2_Glob[8][7] = 10;
|
||||
if (!silent)
|
||||
{
|
||||
write("Dhrystone Benchmark, Version 2.1 (Language: LPC)\n");
|
||||
write("Execution starts, " + Number_Of_Runs + " runs through Dhrystone\n");
|
||||
}
|
||||
Begin_Time = times();
|
||||
for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) {
|
||||
Proc_5();
|
||||
Proc_4();
|
||||
Int_1_Loc = 2;
|
||||
Int_2_Loc = 3;
|
||||
Str_2_Loc = "DHRYSTONE PROGRAM, 2'ND STRING";
|
||||
Enum_Loc = Ident_2;
|
||||
Bool_Glob = !Func_2(Str_1_Loc, Str_2_Loc);
|
||||
while (Int_1_Loc < Int_2_Loc) {
|
||||
Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
|
||||
Proc_7(Int_1_Loc, Int_2_Loc, &Int_3_Loc);
|
||||
Int_1_Loc += 1;
|
||||
}
|
||||
Proc_8(Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
|
||||
Proc_1(Ptr_Glob);
|
||||
for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) {
|
||||
if (Enum_Loc == Func_1(Ch_Index, 'C')) {
|
||||
Proc_6(Ident_1, &Enum_Loc);
|
||||
Str_2_Loc = "DHRYSTONE PROGRAM, 3'RD STRING";
|
||||
Int_2_Loc = Run_Index;
|
||||
Int_Glob = Run_Index;
|
||||
}
|
||||
}
|
||||
Int_2_Loc = Int_2_Loc * Int_1_Loc;
|
||||
Int_1_Loc = Int_2_Loc / Int_3_Loc;
|
||||
Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
|
||||
Proc_2(&Int_1_Loc);
|
||||
}
|
||||
End_Time = times();
|
||||
if (!silent)
|
||||
{
|
||||
write("Execution ends.\n");
|
||||
write("Final values of the variables used in the benchmark:\n\n");
|
||||
printf("Int_Glob: %d\n", Int_Glob);
|
||||
printf(" should be: %d\n", 5);
|
||||
printf("Bool_Glob: %d\n", Bool_Glob);
|
||||
printf(" should be: %d\n", 1);
|
||||
printf("Ch_1_Glob: %c\n", Ch_1_Glob);
|
||||
printf(" should be: %c\n", 'A');
|
||||
printf("Ch_2_Glob: %c\n", Ch_2_Glob);
|
||||
printf(" should be: %c\n", 'B');
|
||||
printf("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]);
|
||||
printf(" should be: %d\n", 7);
|
||||
printf("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]);
|
||||
printf(" should be: Number_Of_Runs + 10\n");
|
||||
#if 0
|
||||
printf("Ptr_Glob->\n");
|
||||
printf(" Ptr_Comp: %O\n", Ptr_Glob["Ptr_Comp"]);
|
||||
printf(" should be: (implementation-dependent)\n");
|
||||
#endif
|
||||
printf(" Discr: %d\n", Ptr_Glob["Discr"]);
|
||||
printf(" should be: %d\n", 0);
|
||||
printf(" Enum_Comp: %d\n", Ptr_Glob["var_1"][Enum_Comp]);
|
||||
printf(" should be: %d\n", 2);
|
||||
printf(" Int_Comp: %d\n", Ptr_Glob["var_1"][Int_Comp]);
|
||||
printf(" should be: %d\n", 17);
|
||||
printf(" Str_Comp: %s\n", Ptr_Glob["var_1"][Str_Comp]);
|
||||
printf(" should be: DHRYSTONE PROGRAM, SOME STRING\n");
|
||||
#if 0
|
||||
printf("Next_Ptr_Glob->\n");
|
||||
printf(" Ptr_Comp: %O\n", Next_Ptr_Glob["Ptr_Comp"]);
|
||||
printf(" should be: (implementation-dependent), same as above\n");
|
||||
#endif
|
||||
printf(" Discr: %d\n", Next_Ptr_Glob["Discr"]);
|
||||
printf(" should be: %d\n", 0);
|
||||
printf(" Enum_Comp: %d\n", Next_Ptr_Glob["var_1"][Enum_Comp]);
|
||||
printf(" should be: %d\n", 1);
|
||||
printf(" Int_Comp: %d\n", Next_Ptr_Glob["var_1"][Int_Comp]);
|
||||
printf(" should be: %d\n", 18);
|
||||
printf(" Str_Comp: %s\n", Next_Ptr_Glob["var_1"][Str_Comp]);
|
||||
printf(" should be: DHRYSTONE PROGRAM, SOME STRING\n");
|
||||
printf("Int_1_Loc: %d\n", Int_1_Loc);
|
||||
printf(" should be: %d\n", 5);
|
||||
printf("Int_2_Loc: %d\n", Int_2_Loc);
|
||||
printf(" should be: %d\n", 13);
|
||||
printf("Int_3_Loc: %d\n", Int_3_Loc);
|
||||
printf(" should be: %d\n", 7);
|
||||
printf("Enum_Loc: %d\n", Enum_Loc);
|
||||
printf(" should be: %d\n", 1);
|
||||
printf("Str_1_Loc: %s\n", Str_1_Loc);
|
||||
printf(" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
|
||||
printf("Str_2_Loc: %s\n", Str_2_Loc);
|
||||
printf(" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
|
||||
printf("\n");
|
||||
}
|
||||
User_Time = End_Time - Begin_Time;
|
||||
if (User_Time <= 0) {
|
||||
if (!silent) {
|
||||
printf("Your rusage() doesn't seem to work: User_Time is %d.\n", User_Time);
|
||||
write("\n");
|
||||
}
|
||||
} else if (User_Time < (2*100)) {
|
||||
if (!silent) {
|
||||
write("Measured time too small to obtain meaningful results\n");
|
||||
write("Please increase number of runs\n");
|
||||
write("\n");
|
||||
}
|
||||
} else {
|
||||
Milliseconds = to_float(User_Time) / Number_Of_Runs;
|
||||
Dhrystones_Per_Second = 1000.0 * Number_Of_Runs / User_Time;
|
||||
if (!silent) {
|
||||
printf ("Milliseconds for one run through Dhrystone: ");
|
||||
printf ("%6.1f \n", Milliseconds);
|
||||
printf ("Dhrystones per Second: ");
|
||||
printf ("%6.1f \n", Dhrystones_Per_Second);
|
||||
}
|
||||
}
|
||||
|
||||
return Dhrystones_Per_Second;
|
||||
}
|
||||
|
||||
void Proc_1(mapping Ptr_Val_Par) {
|
||||
mapping Next_Record;
|
||||
|
||||
Next_Record = Ptr_Val_Par["Ptr_Comp"];
|
||||
Ptr_Val_Par["Ptr_Comp"] = copy_record(Ptr_Glob);
|
||||
Ptr_Val_Par["var_1"][Int_Comp] = 5;
|
||||
Next_Record["var_1"][Str_Comp] = Ptr_Val_Par["var_1"][Str_Comp];
|
||||
Next_Record["var_1"][Int_Comp] = Ptr_Val_Par["var_1"][Int_Comp];
|
||||
Next_Record["Ptr_Comp"] = Ptr_Val_Par["Ptr_Comp"];
|
||||
Proc_3(&(Next_Record["Ptr_Comp"]));
|
||||
if (Next_Record["Discr"] == Ident_1) {
|
||||
Next_Record["var_1"][Int_Comp] = 6;
|
||||
Proc_6( Ptr_Val_Par["var_1"][Enum_Comp],
|
||||
&(Next_Record["var_1"][Enum_Comp]));
|
||||
Next_Record["Ptr_Comp"] = Ptr_Glob["Ptr_Comp"];
|
||||
Proc_7( Next_Record["var_1"][Int_Comp], 10,
|
||||
&(Next_Record["var_1"][Int_Comp]));
|
||||
} else
|
||||
Ptr_Val_Par = copy_record(Ptr_Val_Par["Ptr_Comp"]);
|
||||
}
|
||||
|
||||
void Proc_2(int Int_Par_Ref) {
|
||||
int Int_Loc, Enum_Loc;
|
||||
|
||||
Int_Loc = Int_Par_Ref + 10;
|
||||
do
|
||||
if (Ch_1_Glob == 'A') {
|
||||
Int_Loc -= 1;
|
||||
Int_Par_Ref = Int_Loc - Int_Glob;
|
||||
Enum_Loc = Ident_1;
|
||||
} while (Enum_Loc != Ident_1);
|
||||
}
|
||||
|
||||
void Proc_3(mapping Ptr_Ref_Par) {
|
||||
if (Ptr_Glob != 0)
|
||||
Ptr_Ref_Par = Ptr_Glob["Ptr_Comp"];
|
||||
Proc_7(10, Int_Glob, &(Ptr_Glob["var_1"][Int_Comp]));
|
||||
}
|
||||
|
||||
void Proc_4() {
|
||||
int Bool_Loc;
|
||||
Bool_Loc = Ch_1_Glob == 'A';
|
||||
Bool_Glob = Bool_Loc | Bool_Glob;
|
||||
Ch_2_Glob = 'B';
|
||||
}
|
||||
|
||||
void Proc_5() {
|
||||
Ch_1_Glob = 'A';
|
||||
Bool_Glob = 0 ;
|
||||
}
|
||||
|
||||
void Proc_6(int Enum_Val_Par, int Enum_Ref_Par) {
|
||||
Enum_Ref_Par = Enum_Val_Par;
|
||||
if (!Func_3(Enum_Val_Par))
|
||||
Enum_Ref_Par = Ident_4;
|
||||
switch (Enum_Val_Par) {
|
||||
case Ident_1:
|
||||
Enum_Ref_Par = Ident_1;
|
||||
break;
|
||||
case Ident_2:
|
||||
if (Int_Glob > 100)
|
||||
Enum_Ref_Par = Ident_1;
|
||||
else
|
||||
Enum_Ref_Par = Ident_4;
|
||||
break;
|
||||
case Ident_3:
|
||||
Enum_Ref_Par = Ident_2;
|
||||
break;
|
||||
case Ident_4:
|
||||
break;
|
||||
case Ident_5:
|
||||
Enum_Ref_Par = Ident_3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Proc_7(int Int_1_Par_Val, int Int_2_Par_Val, int Int_Par_Ref) {
|
||||
int Int_Loc;
|
||||
|
||||
Int_Loc = Int_1_Par_Val + 2;
|
||||
Int_Par_Ref = Int_2_Par_Val + Int_Loc;
|
||||
}
|
||||
|
||||
void Proc_8 (mixed *Arr_1_Par_Ref, mixed *Arr_2_Par_Ref,
|
||||
int Int_1_Par_Val, int Int_2_Par_Val) {
|
||||
int Int_Index, Int_Loc;
|
||||
|
||||
Int_Loc = Int_1_Par_Val + 5;
|
||||
Arr_1_Par_Ref[Int_Loc] = Int_2_Par_Val;
|
||||
Arr_1_Par_Ref[Int_Loc + 1] = Arr_1_Par_Ref[Int_Loc];
|
||||
Arr_1_Par_Ref[Int_Loc + 30] = Int_Loc;
|
||||
for (Int_Index = Int_Loc; Int_Index <= Int_Loc + 1; ++Int_Index)
|
||||
Arr_2_Par_Ref[Int_Loc][Int_Index] = Int_Loc;
|
||||
Arr_2_Par_Ref[Int_Loc][Int_Loc - 1] += 1;
|
||||
Arr_2_Par_Ref[Int_Loc + 20][Int_Loc] = Arr_1_Par_Ref[Int_Loc];
|
||||
Int_Glob = 5;
|
||||
}
|
||||
|
||||
int Func_1(int Ch_1_Par_Val, int Ch_2_Par_Val) {
|
||||
int Ch_1_Loc, Ch_2_Loc;
|
||||
|
||||
Ch_1_Loc = Ch_1_Par_Val;
|
||||
Ch_2_Loc = Ch_1_Loc;
|
||||
if (Ch_2_Loc != Ch_2_Par_Val)
|
||||
return Ident_1;
|
||||
else {
|
||||
Ch_1_Glob = Ch_1_Loc;
|
||||
return Ident_2;
|
||||
}
|
||||
}
|
||||
|
||||
int Func_2(string Str_1_Par_Ref, string Str_2_Par_Ref) {
|
||||
int Int_Loc, Ch_Loc;
|
||||
|
||||
Int_Loc = 2;
|
||||
while (Int_Loc <= 2)
|
||||
if (Func_1(Str_1_Par_Ref[Int_Loc], Str_2_Par_Ref[Int_Loc + 1]) == Ident_1) {
|
||||
Ch_Loc = 'A';
|
||||
Int_Loc += 1;
|
||||
}
|
||||
if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
|
||||
Int_Loc = 7;
|
||||
if (Ch_Loc == 'R')
|
||||
return 1;
|
||||
else {
|
||||
if (Str_1_Par_Ref > Str_2_Par_Ref) {
|
||||
Int_Loc += 7;
|
||||
Int_Glob = Int_Loc;
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int Func_3(int Enum_Par_Val) {
|
||||
int Enum_Loc;
|
||||
|
||||
Enum_Loc = Enum_Par_Val;
|
||||
if (Enum_Loc == Ident_3)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
381
mudlib/dhrystone2.c
Normal file
381
mudlib/dhrystone2.c
Normal file
|
@ -0,0 +1,381 @@
|
|||
//===========================================================================
|
||||
// Dhrystone-2.1 Benchmark for LPC
|
||||
//
|
||||
// Don't take this too serious :-) Sven C. Dack
|
||||
//
|
||||
// Compared to the original LPC dhrystone, this one has been modified
|
||||
// to make less indirect data accesses in order to bring it more in
|
||||
// line with Python's pystone.
|
||||
//===========================================================================
|
||||
|
||||
#define Default_Number_Of_Runs 1000
|
||||
|
||||
#pragma strong_types
|
||||
|
||||
//===========================================================================
|
||||
// Support functions to simulate memory allocation and other stuff..
|
||||
|
||||
mixed *alloc_array_50() { return allocate(50); }
|
||||
|
||||
mixed *alloc_array_50_50() {
|
||||
mixed *arr;
|
||||
int i;
|
||||
|
||||
for (i = 50, arr = allocate(50); i--; arr[i] = allocate(50));
|
||||
return arr;
|
||||
}
|
||||
|
||||
mixed * alloc_record() {
|
||||
#define M_PTR_COMP 0
|
||||
#define M_DISCR 1
|
||||
#define M_ENUM_COMP 2
|
||||
#define M_INT_COMP 3
|
||||
#define M_STR_COMP 4
|
||||
#define M_LENGTH 5
|
||||
return ({ /* M_PTR_COMP */ 0
|
||||
, /* M_DISCR */ 0
|
||||
, /* M_ENUM_COMP */ 0
|
||||
, /* M_INT_COMP */ 0
|
||||
, /* M_STR_COMP */ ""
|
||||
});
|
||||
}
|
||||
|
||||
mixed * copy_record(mixed * rec) {
|
||||
mixed * r;
|
||||
|
||||
return copy(rec);
|
||||
}
|
||||
|
||||
int times() {
|
||||
int *ru;
|
||||
|
||||
ru = rusage();
|
||||
return ru[0] + ru[1];
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// The global variables.
|
||||
|
||||
#define Ident_1 0
|
||||
#define Ident_2 1
|
||||
#define Ident_3 2
|
||||
#define Ident_4 3
|
||||
#define Ident_5 4
|
||||
|
||||
#define Enum_Comp 0
|
||||
#define Int_Comp 1
|
||||
#define Str_Comp 2
|
||||
|
||||
mixed * Ptr_Glob, Next_Ptr_Glob;
|
||||
int Int_Glob;
|
||||
int Bool_Glob;
|
||||
int Ch_1_Glob, Ch_2_Glob;
|
||||
mixed *Arr_1_Glob;
|
||||
mixed *Arr_2_Glob;
|
||||
int Begin_Time, End_Time, User_Time;
|
||||
float Milliseconds, Dhrystones_Per_Second;
|
||||
|
||||
//===========================================================================
|
||||
// Prototypes all functions (including those defined later).
|
||||
|
||||
void Proc_1(mixed * m1);
|
||||
int Proc_2(int i1);
|
||||
mixed * Proc_3(mixed * m1);
|
||||
void Proc_4();
|
||||
void Proc_5();
|
||||
int Proc_6(int i1);
|
||||
int Proc_7(int i1, int i2);
|
||||
void Proc_8(mixed *a1, mixed *a2, int i1, int i2);
|
||||
int Func_1(int i1, int i2);
|
||||
int Func_2(string s1, string s2);
|
||||
int Func_3(int i1);
|
||||
|
||||
//===========================================================================
|
||||
|
||||
float main(int Number_Of_Runs, int silent) {
|
||||
int Int_1_Loc, Int_2_Loc, Int_3_Loc;
|
||||
int Ch_Index;
|
||||
int Enum_Loc;
|
||||
string Str_1_Loc, Str_2_Loc;
|
||||
int Run_Index;
|
||||
|
||||
if (Number_Of_Runs <= 0)
|
||||
Number_Of_Runs = Default_Number_Of_Runs;
|
||||
|
||||
Arr_1_Glob = alloc_array_50();
|
||||
Arr_2_Glob = alloc_array_50_50();
|
||||
Str_1_Loc = "";
|
||||
Str_2_Loc = "";
|
||||
Next_Ptr_Glob = alloc_record();
|
||||
Ptr_Glob = alloc_record();
|
||||
Ptr_Glob[M_PTR_COMP] = Next_Ptr_Glob;
|
||||
Ptr_Glob[M_DISCR] = Ident_1;
|
||||
Ptr_Glob[M_ENUM_COMP] = Ident_3;
|
||||
Ptr_Glob[M_INT_COMP] = 40;
|
||||
Ptr_Glob[M_STR_COMP] = "DHRYSTONE PROGRAM, SOME STRING";
|
||||
Str_1_Loc = "DHRYSTONE PROGRAM, 1'ST STRING";
|
||||
Arr_2_Glob[8][7] = 10;
|
||||
if (!silent) {
|
||||
write("Dhrystone Benchmark, Version 2.1 (Language: LPC)\n");
|
||||
write("Execution starts, " + Number_Of_Runs + " runs through Dhrystone\n");
|
||||
}
|
||||
Begin_Time = times();
|
||||
for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) {
|
||||
Proc_5();
|
||||
Proc_4();
|
||||
Int_1_Loc = 2;
|
||||
Int_2_Loc = 3;
|
||||
Str_2_Loc = "DHRYSTONE PROGRAM, 2'ND STRING";
|
||||
Enum_Loc = Ident_2;
|
||||
Bool_Glob = !Func_2(Str_1_Loc, Str_2_Loc);
|
||||
while (Int_1_Loc < Int_2_Loc) {
|
||||
Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
|
||||
Int_3_Loc = Proc_7(Int_1_Loc, Int_2_Loc);
|
||||
Int_1_Loc += 1;
|
||||
}
|
||||
Proc_8(Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
|
||||
Proc_1(Ptr_Glob);
|
||||
for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) {
|
||||
if (Enum_Loc == Func_1(Ch_Index, 'C')) {
|
||||
Enum_Loc = Proc_6(Ident_1);
|
||||
//Str_2_Loc = "DHRYSTONE PROGRAM, 3'RD STRING";
|
||||
//Int_2_Loc = Run_Index;
|
||||
//Int_Glob = Run_Index;
|
||||
}
|
||||
}
|
||||
Int_2_Loc = Int_2_Loc * Int_1_Loc;
|
||||
Int_1_Loc = Int_2_Loc / Int_3_Loc;
|
||||
Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
|
||||
Int_1_Loc = Proc_2(Int_1_Loc);
|
||||
}
|
||||
End_Time = times();
|
||||
if (!silent)
|
||||
{
|
||||
write("Execution ends.\n");
|
||||
write("Final values of the variables used in the benchmark:\n\n");
|
||||
printf("Int_Glob: %d\n", Int_Glob);
|
||||
printf(" should be: %d\n", 5);
|
||||
printf("Bool_Glob: %d\n", Bool_Glob);
|
||||
printf(" should be: %d\n", 1);
|
||||
printf("Ch_1_Glob: %c\n", Ch_1_Glob);
|
||||
printf(" should be: %c\n", 'A');
|
||||
printf("Ch_2_Glob: %c\n", Ch_2_Glob);
|
||||
printf(" should be: %c\n", 'B');
|
||||
printf("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]);
|
||||
printf(" should be: %d\n", 7);
|
||||
printf("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]);
|
||||
printf(" should be: Number_Of_Runs + 10\n");
|
||||
#if 0
|
||||
printf("Ptr_Glob->\n");
|
||||
printf(" Ptr_Comp: %O\n", Ptr_Glob[M_PTR_COMP]);
|
||||
printf(" should be: (implementation-dependent)\n");
|
||||
#endif
|
||||
printf(" Discr: %d\n", Ptr_Glob[M_DISCR]);
|
||||
printf(" should be: %d\n", 0);
|
||||
printf(" Enum_Comp: %d\n", Ptr_Glob[M_ENUM_COMP]);
|
||||
printf(" should be: %d\n", 2);
|
||||
printf(" Int_Comp: %d\n", Ptr_Glob[M_INT_COMP]);
|
||||
printf(" should be: %d\n", 17);
|
||||
printf(" Str_Comp: %s\n", Ptr_Glob[M_STR_COMP]);
|
||||
printf(" should be: DHRYSTONE PROGRAM, SOME STRING\n");
|
||||
#if 0
|
||||
printf("Next_Ptr_Glob->\n");
|
||||
printf(" Ptr_Comp: %O\n", Next_Ptr_Glob[M_PTR_COMP]);
|
||||
printf(" should be: (implementation-dependent), same as above\n");
|
||||
#endif
|
||||
printf(" Discr: %d\n", Next_Ptr_Glob[M_DISCR]);
|
||||
printf(" should be: %d\n", 0);
|
||||
printf(" Enum_Comp: %d\n", Next_Ptr_Glob[M_ENUM_COMP]);
|
||||
printf(" should be: %d\n", 1);
|
||||
printf(" Int_Comp: %d\n", Next_Ptr_Glob[M_INT_COMP]);
|
||||
printf(" should be: %d\n", 18);
|
||||
printf(" Str_Comp: %s\n", Next_Ptr_Glob[M_STR_COMP]);
|
||||
printf(" should be: DHRYSTONE PROGRAM, SOME STRING\n");
|
||||
printf("Int_1_Loc: %d\n", Int_1_Loc);
|
||||
printf(" should be: %d\n", 5);
|
||||
printf("Int_2_Loc: %d\n", Int_2_Loc);
|
||||
printf(" should be: %d\n", 13);
|
||||
printf("Int_3_Loc: %d\n", Int_3_Loc);
|
||||
printf(" should be: %d\n", 7);
|
||||
printf("Enum_Loc: %d\n", Enum_Loc);
|
||||
printf(" should be: %d\n", 1);
|
||||
printf("Str_1_Loc: %s\n", Str_1_Loc);
|
||||
printf(" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
|
||||
printf("Str_2_Loc: %s\n", Str_2_Loc);
|
||||
printf(" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
|
||||
printf("\n");
|
||||
}
|
||||
User_Time = End_Time - Begin_Time;
|
||||
if (User_Time <= 0) {
|
||||
if (!silent) {
|
||||
printf("Your rusage() doesn't seem to work: User_Time is %d.\n", User_Time);
|
||||
write("\n");
|
||||
}
|
||||
} else if (User_Time < (2*100)) {
|
||||
if (!silent) {
|
||||
write("Measured time too small to obtain meaningful results\n");
|
||||
write("Please increase number of runs\n");
|
||||
write("\n");
|
||||
}
|
||||
} else {
|
||||
Milliseconds = to_float(User_Time) / Number_Of_Runs;
|
||||
Dhrystones_Per_Second = 1000.0 * Number_Of_Runs / User_Time;
|
||||
if (!silent)
|
||||
{
|
||||
printf ("Milliseconds for one run through Dhrystone: ");
|
||||
printf ("%6.1f \n", Milliseconds);
|
||||
printf ("Dhrystones per Second: ");
|
||||
printf ("%6.1f \n", Dhrystones_Per_Second);
|
||||
}
|
||||
}
|
||||
|
||||
return Dhrystones_Per_Second;
|
||||
}
|
||||
|
||||
void Proc_1(mixed * Ptr_Val_Par) {
|
||||
mixed * Next_Record;
|
||||
|
||||
Next_Record = Ptr_Val_Par[M_PTR_COMP];
|
||||
Ptr_Val_Par[M_PTR_COMP] = copy_record(Ptr_Glob);
|
||||
Ptr_Val_Par[M_INT_COMP] = 5;
|
||||
Next_Record[M_STR_COMP] = Ptr_Val_Par[M_STR_COMP];
|
||||
Next_Record[M_INT_COMP] = Ptr_Val_Par[M_INT_COMP];
|
||||
Next_Record[M_PTR_COMP] = Ptr_Val_Par[M_PTR_COMP];
|
||||
Next_Record[M_PTR_COMP] = Proc_3(Next_Record[M_PTR_COMP]);
|
||||
if (Next_Record[M_DISCR] == Ident_1) {
|
||||
Next_Record[M_INT_COMP] = 6;
|
||||
Next_Record[M_ENUM_COMP] = Proc_6(Ptr_Val_Par[M_ENUM_COMP]);
|
||||
Next_Record[M_PTR_COMP] = Ptr_Glob[M_PTR_COMP];
|
||||
Next_Record[M_INT_COMP] = Proc_7( Next_Record[M_INT_COMP], 10);
|
||||
} else
|
||||
Ptr_Val_Par = copy_record(Ptr_Val_Par[M_PTR_COMP]);
|
||||
}
|
||||
|
||||
int Proc_2(int Int_Par) {
|
||||
int Int_Loc, Enum_Loc;
|
||||
|
||||
Int_Loc = Int_Par + 10;
|
||||
do
|
||||
if (Ch_1_Glob == 'A') {
|
||||
Int_Loc -= 1;
|
||||
Int_Par = Int_Loc - Int_Glob;
|
||||
Enum_Loc = Ident_1;
|
||||
}
|
||||
while (Enum_Loc != Ident_1);
|
||||
return Int_Par;
|
||||
}
|
||||
|
||||
mixed * Proc_3(mixed * Ptr_Ref_Par) {
|
||||
if (Ptr_Glob != 0)
|
||||
Ptr_Ref_Par = Ptr_Glob[M_PTR_COMP];
|
||||
Ptr_Glob[M_INT_COMP] = Proc_7(10, Int_Glob);
|
||||
return Ptr_Ref_Par;
|
||||
}
|
||||
|
||||
void Proc_4() {
|
||||
int Bool_Loc;
|
||||
Bool_Loc = Ch_1_Glob == 'A';
|
||||
Bool_Glob = Bool_Loc | Bool_Glob;
|
||||
Ch_2_Glob = 'B';
|
||||
}
|
||||
|
||||
void Proc_5() {
|
||||
Ch_1_Glob = 'A';
|
||||
Bool_Glob = 0 ;
|
||||
}
|
||||
|
||||
int Proc_6(int Enum_Val_Par) {
|
||||
int Enum_Par_Out;
|
||||
Enum_Par_Out = Enum_Val_Par;
|
||||
if (!Func_3(Enum_Val_Par))
|
||||
Enum_Par_Out = Ident_4;
|
||||
switch (Enum_Val_Par) {
|
||||
case Ident_1:
|
||||
Enum_Par_Out = Ident_1;
|
||||
break;
|
||||
case Ident_2:
|
||||
if (Int_Glob > 100)
|
||||
Enum_Par_Out = Ident_1;
|
||||
else
|
||||
Enum_Par_Out = Ident_4;
|
||||
break;
|
||||
case Ident_3:
|
||||
Enum_Par_Out = Ident_2;
|
||||
break;
|
||||
case Ident_4:
|
||||
break;
|
||||
case Ident_5:
|
||||
Enum_Par_Out = Ident_3;
|
||||
break;
|
||||
}
|
||||
return Enum_Par_Out;
|
||||
}
|
||||
|
||||
int Proc_7(int Int_1_Par_Val, int Int_2_Par_Val) {
|
||||
int Int_Loc;
|
||||
|
||||
Int_Loc = Int_1_Par_Val + 2;
|
||||
return Int_2_Par_Val + Int_Loc;
|
||||
}
|
||||
|
||||
void Proc_8 (mixed *Arr_1_Par_Ref, mixed *Arr_2_Par_Ref,
|
||||
int Int_1_Par_Val, int Int_2_Par_Val) {
|
||||
int Int_Index, Int_Loc;
|
||||
|
||||
Int_Loc = Int_1_Par_Val + 5;
|
||||
Arr_1_Par_Ref[Int_Loc] = Int_2_Par_Val;
|
||||
Arr_1_Par_Ref[Int_Loc + 1] = Arr_1_Par_Ref[Int_Loc];
|
||||
Arr_1_Par_Ref[Int_Loc + 30] = Int_Loc;
|
||||
for (Int_Index = Int_Loc; Int_Index <= Int_Loc + 1; ++Int_Index)
|
||||
Arr_2_Par_Ref[Int_Loc][Int_Index] = Int_Loc;
|
||||
Arr_2_Par_Ref[Int_Loc][Int_Loc - 1] += 1;
|
||||
Arr_2_Par_Ref[Int_Loc + 20][Int_Loc] = Arr_1_Par_Ref[Int_Loc];
|
||||
Int_Glob = 5;
|
||||
}
|
||||
|
||||
int Func_1(int Ch_1_Par_Val, int Ch_2_Par_Val) {
|
||||
int Ch_1_Loc, Ch_2_Loc;
|
||||
|
||||
Ch_1_Loc = Ch_1_Par_Val;
|
||||
Ch_2_Loc = Ch_1_Loc;
|
||||
if (Ch_2_Loc != Ch_2_Par_Val)
|
||||
return Ident_1;
|
||||
else {
|
||||
Ch_1_Glob = Ch_1_Loc;
|
||||
return Ident_2;
|
||||
}
|
||||
}
|
||||
|
||||
int Func_2(string Str_1_Par_Ref, string Str_2_Par_Ref) {
|
||||
int Int_Loc, Ch_Loc;
|
||||
|
||||
Int_Loc = 2;
|
||||
while (Int_Loc <= 2)
|
||||
if (Func_1(Str_1_Par_Ref[Int_Loc], Str_2_Par_Ref[Int_Loc + 1]) == Ident_1) {
|
||||
Ch_Loc = 'A';
|
||||
Int_Loc += 1;
|
||||
}
|
||||
if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
|
||||
Int_Loc = 7;
|
||||
if (Ch_Loc == 'R')
|
||||
return 1;
|
||||
else {
|
||||
if (Str_1_Par_Ref > Str_2_Par_Ref) {
|
||||
Int_Loc += 7;
|
||||
Int_Glob = Int_Loc;
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int Func_3(int Enum_Par_Val) {
|
||||
int Enum_Loc;
|
||||
|
||||
Enum_Loc = Enum_Par_Val;
|
||||
if (Enum_Loc == Ident_3)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
112
mudlib/dns_resolve.c
Normal file
112
mudlib/dns_resolve.c
Normal file
|
@ -0,0 +1,112 @@
|
|||
void
|
||||
dns_resolve (string hostname, closure callback)
|
||||
|
||||
// Try to lookup the IP for the fully qualified <hostname> using direct ERQ
|
||||
// communication. Once the name is resolved, call callback() with the
|
||||
// resolved name as parameter.
|
||||
//
|
||||
// Note: If the ERQ is unavailable, callback() is called with the original
|
||||
// hostname.
|
||||
//
|
||||
// preferably to be installed as "simul efun." latest version available
|
||||
// in world/net/library.i of psycMUVE (download from http://muve.pages.de)
|
||||
// this version runs with broken and fixed erq's alike.
|
||||
//
|
||||
// Written by Tobias@Heldensaga and Arne@Elridion.
|
||||
|
||||
{
|
||||
closure c;
|
||||
|
||||
if (sscanf(hostname,"%~D.%~D.%~D.%~D") == 4) {
|
||||
// hostname is an IP already. Just call the callback.
|
||||
funcall(callback, hostname);
|
||||
return;
|
||||
}
|
||||
|
||||
c = lambda( ({ 'name }), ({
|
||||
(#'switch), ({ #'sizeof, 'name }),
|
||||
({ 4 }), // ERQ: name resolved!
|
||||
({ (#',),
|
||||
({ (#'=),'name,({ (#'map),'name,#'&,255 }) }),
|
||||
({ (#'=),'name,
|
||||
({
|
||||
(#'sprintf),"%d.%d.%d.%d",
|
||||
({ #'[, 'name, 0 }),
|
||||
({ #'[, 'name, 1 }),
|
||||
({ #'[, 'name, 2 }),
|
||||
({ #'[, 'name, 3 })
|
||||
})
|
||||
}),
|
||||
({ (#'funcall), callback, 'name })
|
||||
}),
|
||||
(#'break),
|
||||
({ 6 + strlen(hostname) }), // XERQ
|
||||
({ (#',),
|
||||
({ (#'=),'name,({ (#'map),'name,#'&,255 }) }),
|
||||
({ (#'=),'name,
|
||||
({
|
||||
(#'sprintf),"%d.%d.%d.%d",
|
||||
({ #'[, 'name, 1
|
||||
}),
|
||||
({ #'[, 'name, 2
|
||||
}),
|
||||
({ #'[, 'name, 3
|
||||
}),
|
||||
({ #'[, 'name, 4 })
|
||||
})
|
||||
}),
|
||||
({ (#'funcall), callback, 'name })
|
||||
}),
|
||||
(#'break),
|
||||
({ #'default }),
|
||||
({
|
||||
#'debug_message, "FATAL: ERQ could not resolve \""
|
||||
+ hostname + "\". The callback will not be called.\n"
|
||||
}),
|
||||
(#'break)
|
||||
})
|
||||
);
|
||||
#ifdef THEDAYWEARESURENOONERUNSABUGGYERQ
|
||||
if (!send_erq(ERQ_LOOKUP, hostname, c))
|
||||
#else
|
||||
// appending the zero byte fixes a bug in erq. sick!
|
||||
if (!send_erq(ERQ_LOOKUP, to_array(hostname) + ({ 0 }), c))
|
||||
#endif
|
||||
{
|
||||
// if we cannot resolve using erq, we'll send back the hostname,
|
||||
// so the driver can do a blocking resolve itself (needed for
|
||||
// net_connect())
|
||||
funcall(callback, hostname);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
// typical usage example taken from PSYCmuve world/net/irc/gatebot.c
|
||||
// this ensures a non-blocking connect to a remote service even by name.
|
||||
//
|
||||
connect(host, port) {
|
||||
unless (host) host = IRCNET_HOST;
|
||||
unless (port) port = IRCNET_PORT;
|
||||
D2( D("IRCgate resolving hostname "+ host +"\n"); )
|
||||
dns_resolve(host, lambda(({ 'result }),
|
||||
({ #'connect2, 'result, port })));
|
||||
}
|
||||
connect2(host, port) {
|
||||
#if __EFUN_DEFINED__(net_connect)
|
||||
int res;
|
||||
|
||||
D0( D(S("IRCgate attempting connect to %O:%O\n", host, port)); )
|
||||
res = net_connect(host, port);
|
||||
if (res) monitor_report("_failure_network_connect_call",
|
||||
"ircbot: connect to "+host+" returns "+ res);
|
||||
return res;
|
||||
#else
|
||||
D2( D("IRCgate * Oh, driver does not provide net_connect()\n"); )
|
||||
return -9;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* EXAMPLE */
|
||||
|
214
mudlib/erq-tool.c
Normal file
214
mudlib/erq-tool.c
Normal file
|
@ -0,0 +1,214 @@
|
|||
#include <erq.h>
|
||||
|
||||
object command_giver;
|
||||
int *ticket;
|
||||
int verbose = 1;
|
||||
|
||||
short() {
|
||||
return "Erq tool";
|
||||
}
|
||||
|
||||
id(s) {
|
||||
switch(s) {
|
||||
case "erq-tool":
|
||||
case "erq tool":
|
||||
case "erq":
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
long() {
|
||||
return "\
|
||||
This tool allows you to use the ERQ_SPAWN / ERQ_SEND / ERQ_KILL requests\n\
|
||||
of the external command demon.\n\
|
||||
\n\
|
||||
Usage:\n\
|
||||
e <program> <arguments>\n\
|
||||
start <program> with <arguments>. Blanks, tabs and backslashes have to be\n\
|
||||
quoted if desired as a part of the program name and / or an argument.\n\
|
||||
The text is directly sent to the ERQ_SPAWN request, which does the\n\
|
||||
commandline interpretation wrt. blanks and whitespace.\n\
|
||||
You can only start a new program with this tool while it is not\n\
|
||||
currently controlling another one.\n\
|
||||
e <text>\n\
|
||||
send <text> to the standard input of the running program.\n\
|
||||
er\n\
|
||||
send a single newline to the standard input of the running program.\n\
|
||||
ekill\n\
|
||||
kill the running program\n\
|
||||
ekill <signal>\n\
|
||||
send <signal> to the running program.\n\
|
||||
everbose\n\
|
||||
toggle verbose mode.\n\
|
||||
econnect\n\
|
||||
send all input to stdin of the running program.\n\
|
||||
\n\
|
||||
output from stdout will be displayed with a prepended single quote,\n\
|
||||
output from stderr will be displayed with a prepended double quote.\n\
|
||||
";
|
||||
}
|
||||
|
||||
get() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
drop(silently) {
|
||||
return query_verb() != "give";
|
||||
}
|
||||
|
||||
init() {
|
||||
add_action("erq", "e");
|
||||
add_action("erq", "er");
|
||||
add_action("ekill", "ekill");
|
||||
add_action("everbose", "everbose");
|
||||
add_action("econnect", "econnect");
|
||||
}
|
||||
|
||||
receive_output(a) {
|
||||
if (!ticket) {
|
||||
switch(a[0]) {
|
||||
case ERQ_OK:
|
||||
write("Command accepted.\n");
|
||||
ticket = a[1..];
|
||||
return;
|
||||
case ERQ_E_ARGLENGTH:
|
||||
write("Too long argument\n");
|
||||
break;
|
||||
case ERQ_E_ARGNUMBER:
|
||||
write("Too many arguments\n");
|
||||
break;
|
||||
case ERQ_E_PATHLEN:
|
||||
write("Too long pathname\n");
|
||||
break;
|
||||
case ERQ_E_ARGFORMAT:
|
||||
write("Syntax error\n");
|
||||
break;
|
||||
case ERQ_E_ILLEGAL:
|
||||
write("Illegal pathname\n");
|
||||
break;
|
||||
case ERQ_E_FORKFAIL:
|
||||
write("Fork failed\n");
|
||||
break;
|
||||
default:
|
||||
write("Unknown error, command rejected\n");
|
||||
break;
|
||||
}
|
||||
command_giver = 0;
|
||||
return;
|
||||
}
|
||||
switch(a[0]) {
|
||||
case ERQ_STDOUT:
|
||||
a[0] = '\'';
|
||||
tell_object(command_giver, to_string(a));
|
||||
return;
|
||||
case ERQ_STDERR:
|
||||
a[0] = '\"';
|
||||
tell_object(command_giver, to_string(a));
|
||||
return;
|
||||
case ERQ_EXITED:
|
||||
tell_object(command_giver,
|
||||
sprintf("Program exited with status %d.\n", a[1]));
|
||||
break;
|
||||
case ERQ_SIGNALED:
|
||||
tell_object(command_giver,
|
||||
sprintf("Program caught signal %d.\n", a[1]));
|
||||
break;
|
||||
case ERQ_E_UNKNOWN:
|
||||
tell_object(command_giver, "Unknown error.\n");
|
||||
break;
|
||||
}
|
||||
command_giver = 0;
|
||||
ticket = 0;
|
||||
}
|
||||
|
||||
send_reply(a, p, s) {
|
||||
switch (a[0]) {
|
||||
case ERQ_OK:
|
||||
if (verbose)
|
||||
tell_object(p, "Ok.\n");
|
||||
break;
|
||||
default:
|
||||
tell_object(p, "Input not fully accepted.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
kill_reply(a, p, s) {
|
||||
switch (a[0]) {
|
||||
case ERQ_OK:
|
||||
if (verbose)
|
||||
tell_object(p, "Ok.\n");
|
||||
break;
|
||||
case ERQ_E_TICKET:
|
||||
tell_object(p, "Trying to kill a dead process\n");
|
||||
break;
|
||||
case ERQ_E_ILLEGAL:
|
||||
tell_object(p, "Illegal signal\n");
|
||||
break;
|
||||
default:
|
||||
tell_object(p, "Kill error.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
erq(s) {
|
||||
if (!s)
|
||||
s = "";
|
||||
if (ticket) {
|
||||
send_erq(ERQ_SEND, ticket+to_array(s)+({'\n'}), lambda(({'a}),
|
||||
({#'send_reply, 'a, command_giver, s})));
|
||||
return 1;
|
||||
} else if (!command_giver) {
|
||||
command_giver = this_player();
|
||||
send_erq(ERQ_SPAWN, s, #'receive_output);
|
||||
return 1;
|
||||
} else {
|
||||
write("Waiting for command to be accepted\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
ekill(s) {
|
||||
int signal;
|
||||
|
||||
if (!ticket) {
|
||||
write("No program running\n");
|
||||
return 1;
|
||||
}
|
||||
if ( !(s && sscanf(s, "%d", signal)) )
|
||||
signal = 9;
|
||||
send_erq(ERQ_KILL, ticket+({0,0,0,signal}), lambda(({'a}),
|
||||
({#'kill_reply, 'a, command_giver, signal})));
|
||||
return 1;
|
||||
}
|
||||
|
||||
everbose(s) {
|
||||
switch(s) {
|
||||
case "on":
|
||||
verbose = 1;
|
||||
return 1;
|
||||
case "off":
|
||||
verbose = 0;
|
||||
return 1;
|
||||
case 0:
|
||||
verbose = !verbose;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
econnect() {
|
||||
write("Use 'edisconnect' to stop.\n");
|
||||
add_action("erq", "", 2);
|
||||
add_action("edisconnect", "edisconnect");
|
||||
add_action("erq", "er");
|
||||
return 1;
|
||||
}
|
||||
|
||||
edisconnect() {
|
||||
remove_action("");
|
||||
remove_action("edisconnect");
|
||||
remove_action("er");
|
||||
return 1;
|
||||
}
|
1255
mudlib/master_skeleton.c
Normal file
1255
mudlib/master_skeleton.c
Normal file
File diff suppressed because it is too large
Load diff
171
mudlib/pgsql.c
Normal file
171
mudlib/pgsql.c
Normal file
|
@ -0,0 +1,171 @@
|
|||
// Example object for the use of PostgreSQL efuns.
|
||||
|
||||
inherit "/i/item";
|
||||
inherit "/i/move";
|
||||
|
||||
#define TP(x) player->tell(x)
|
||||
//#define TP(x) this_player()->tell(x)
|
||||
#include <input_to.h>
|
||||
#include <pgsql.h>
|
||||
#include <lpctypes.h>
|
||||
|
||||
int connected = 0;
|
||||
object player;
|
||||
|
||||
string *keyvalues(mapping m, string key) {
|
||||
string *ret = ({});
|
||||
int i, rows = widthof(m);
|
||||
|
||||
for (i = 0; i < rows; i++) {
|
||||
ret += ({ m[key,i] });
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
string *prettytable (mixed res) {
|
||||
int rows, cols, i, j, total, tmp;
|
||||
string row;
|
||||
string *ret, *fnames, line, *fsizes;
|
||||
|
||||
|
||||
ret = ({});
|
||||
fsizes = ({});
|
||||
cols = sizeof(res);
|
||||
|
||||
if (typeof(res) == T_POINTER) {
|
||||
for (i = 0; i < cols; i++)
|
||||
ret += ({ implode(res[i], ",") });
|
||||
return ret;
|
||||
}
|
||||
|
||||
fnames = m_indices(res);
|
||||
rows = widthof(res);
|
||||
for (i = 0; i < cols; i++) {
|
||||
tmp = max(map(keyvalues(res, fnames[i])+({ fnames[i] }), #'sizeof));
|
||||
total += tmp;
|
||||
fsizes += ({ to_string(tmp) });
|
||||
}
|
||||
total += sizeof(fsizes)*3 + 1;
|
||||
|
||||
ret += ({ sprintf(" +%"+to_string(total-2)+"'-'s+", "") });
|
||||
|
||||
line = " | ";
|
||||
for (j = 0; j < cols; j++) {
|
||||
line += sprintf("%|"+fsizes[j]+"."+fsizes[j]+"s | ", fnames[j]);
|
||||
}
|
||||
ret += ({ line });
|
||||
ret += ({ ret[0] });
|
||||
for (i = 0; i < rows; i++) {
|
||||
line = " | ";
|
||||
for (j = 0; j < cols; j++) {
|
||||
line += sprintf("%-"+fsizes[j]+"."+fsizes[j]+"s | ",
|
||||
res[fnames[j],i]);
|
||||
}
|
||||
ret += ({ line });
|
||||
}
|
||||
ret += ({ ret[0] });
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int result (int nr, mixed res, int id) {
|
||||
string *table;
|
||||
|
||||
TP("\n");
|
||||
switch (nr) {
|
||||
case PGRES_COMMAND_OK:
|
||||
TP(res+"\n");
|
||||
break;
|
||||
case PGRES_TUPLES_OK:
|
||||
if (res) {
|
||||
table = prettytable(res);
|
||||
table += ({ "Rows: "+to_string(widthof(res))+"\n" });
|
||||
TP(implode(table, "\n"));
|
||||
} else {
|
||||
TP("No rows matched.\n");
|
||||
}
|
||||
break;
|
||||
case PGRES_BAD_RESPONSE:
|
||||
case PGRES_NONFATAL_ERROR:
|
||||
case PGRES_FATAL_ERROR:
|
||||
TP(res);
|
||||
break;
|
||||
case PGRES_NOTICE:
|
||||
TP(res);
|
||||
break;
|
||||
case PGCONN_SUCCESS:
|
||||
TP("PG-connection established.\n");
|
||||
connected = 1;
|
||||
break;
|
||||
case PGCONN_FAILED:
|
||||
TP("PG-connection failed: "+res+"\n");
|
||||
connected = 0;
|
||||
break;
|
||||
case PGCONN_ABORTED:
|
||||
TP("PG-connection lost: "+res+"\n");
|
||||
connected = 0;
|
||||
break;
|
||||
}
|
||||
if (connected)
|
||||
tell_object(player, "SQL> ");
|
||||
else
|
||||
tell_object(player, "sql> ");
|
||||
}
|
||||
|
||||
|
||||
int _sql (string str) {
|
||||
string prompt;
|
||||
|
||||
if (str && !connected && (lower_case(str[0..6]) == "connect")) {
|
||||
str = str[8..];
|
||||
if (pg_connect(str, "result") < 0)
|
||||
TP("Error in connect-string");
|
||||
else
|
||||
TP("Connecting...");
|
||||
} else if (str && connected && (lower_case(str) == "disconnect")) {
|
||||
pg_close();
|
||||
connected = 0;
|
||||
TP("Disconnected...");
|
||||
} else if (str && ((lower_case(str) == "exit") || (lower_case(str) == "quit")))
|
||||
return 1;
|
||||
else if (str && strlen(str)) {
|
||||
if (!connected)
|
||||
TP("Connect first, brainy\n");
|
||||
else
|
||||
pg_query(str, RESULT_ASSOC);
|
||||
}
|
||||
|
||||
if (connected)
|
||||
prompt = "SQL> ";
|
||||
else
|
||||
prompt = "sql> ";
|
||||
|
||||
input_to("_sql", INPUT_PROMPT, prompt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sql (string str) {
|
||||
TP("SQL-Shell v0.1a");
|
||||
TP("===============");
|
||||
TP("Commands: connect, disconnect, exit, quit");
|
||||
TP("Everything else is treated as SQL-command");
|
||||
TP("");
|
||||
_sql(str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void init (void) {
|
||||
::init();
|
||||
player = this_player();
|
||||
if (playerp(environment()))
|
||||
add_action("sql", "sql");
|
||||
}
|
||||
|
||||
void create (void) {
|
||||
::create();
|
||||
set_name("sqlshell");
|
||||
set_id(({"sqlshell","sql"}));
|
||||
set_long("Eine SQL-Shell");
|
||||
set_gender("w");
|
||||
}
|
108
mudlib/psyc-tls.c
Normal file
108
mudlib/psyc-tls.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
#include <net.h> // vim syntax=lpc
|
||||
|
||||
/* Wrapper for using the tls_check_certificate() efun.
|
||||
*
|
||||
* If for example the efun returns this raw data:
|
||||
* ({
|
||||
* 0,
|
||||
* ({
|
||||
* "2.5.4.3",
|
||||
* "commonName",
|
||||
* "goodadvice.pages.de"
|
||||
* }),
|
||||
* ({
|
||||
* 0,
|
||||
* 0,
|
||||
* 0,
|
||||
* 0,
|
||||
* 0,
|
||||
* 0,
|
||||
* 0,
|
||||
* 0,
|
||||
* 0,
|
||||
* 0,
|
||||
* 0,
|
||||
* 0,
|
||||
* "2.5.29.17",
|
||||
* "X509v3 Subject Alternative Name",
|
||||
* ({
|
||||
* "dNSName",
|
||||
* "dNSName",
|
||||
* "goodadvice.pages.de",
|
||||
* "1.3.6.1.5.5.7.8.5",
|
||||
* "1.3.6.1.5.5.7.8.5",
|
||||
* "goodadvice.pages.de"
|
||||
* })
|
||||
* })
|
||||
* })
|
||||
*
|
||||
* the wrapper will transform it into:
|
||||
* ([
|
||||
* 0: 0
|
||||
* "2.5.29.17:dNSName": "goodadvice.pages.de",
|
||||
* "2.5.4.3": "goodadvice.pages.de",
|
||||
* "2.5.29.17:1.3.6.1.5.5.7.8.5": "goodadvice.pages.de",
|
||||
* ])*
|
||||
*/
|
||||
|
||||
mapping tls_certificate(object who, int longnames) {
|
||||
mixed *extra, extensions;
|
||||
mapping cert;
|
||||
int i, j;
|
||||
|
||||
cert = ([ ]);
|
||||
#if __EFUN_DEFINED__(tls_check_certificate)
|
||||
# ifdef WANT_S2S_SASL
|
||||
extra = tls_check_certificate(who, 1);
|
||||
unless (extra) return 0;
|
||||
cert[0] = extra[0];
|
||||
extensions = extra[2];
|
||||
extra = extra[1];
|
||||
|
||||
for (i = 0; i < sizeof(extra); i += 3) {
|
||||
mixed t;
|
||||
|
||||
t = cert[extra[i]];
|
||||
unless (t) {
|
||||
cert[extra[i]] = extra[i+2];
|
||||
} else if (stringp(t)) {
|
||||
cert[extra[i]] = ({ t, extra[i+2] });
|
||||
} else if (pointerp(t)) {
|
||||
cert[extra[i]] += ({ extra[i+2] });
|
||||
} else {
|
||||
// should not happen
|
||||
}
|
||||
}
|
||||
if (longnames) {
|
||||
// set up short/long names
|
||||
for (i = 0; i < sizeof(extra); i +=3) {
|
||||
cert[extra[i+1]] = cert[extra[i]];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < sizeof(extensions); i += 3) {
|
||||
string key, mkey;
|
||||
mixed *val;
|
||||
|
||||
unless(extensions[i]) continue;
|
||||
key = extensions[i];
|
||||
val = extensions[i+2];
|
||||
for (j = 0; j < sizeof(val); j += 3) {
|
||||
mixed t;
|
||||
|
||||
mkey = key + ":" + val[j];
|
||||
t = cert[mkey];
|
||||
unless (t) {
|
||||
cert[mkey] = val[j+2];
|
||||
} else if (stringp(t)) {
|
||||
cert[mkey] = ({ t, val[j+2] });
|
||||
} else if (pointerp(t)) {
|
||||
cert[mkey] += ({ val[j+2] });
|
||||
} else {
|
||||
// should not happen
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
return cert;
|
||||
}
|
40
mudlib/query_ip_name.c
Normal file
40
mudlib/query_ip_name.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* IPv4/IPv6 name lookup using ERQ
|
||||
* by Fini <ujastrow@mail.desy.de>
|
||||
* Tue, 9 Mar 2004 08:20:16 +0100 (MET)
|
||||
*/
|
||||
|
||||
void get_ip_name(string ip_num) {
|
||||
[...]
|
||||
num=allocate(4);
|
||||
if (sscanf(ip_num, "%d.%d.%d.%d", num[0], num[1], num[2], num[3])!=4)
|
||||
continue;
|
||||
# ifdef RDNS_DEBUG
|
||||
log_file("IP-NAME",
|
||||
sprintf(" ** RDNS request for IPv4 %s sent\n", ip_num));
|
||||
# endif
|
||||
send_erq(ERQ_RLOOKUP, num, #'_got_ipv4_name);
|
||||
[...]
|
||||
}
|
||||
|
||||
void _got_ipv4_name(int* data, int len) {
|
||||
int* x;
|
||||
string ip_num, ip_nam;
|
||||
if (previous_object()) return; // only the driver may call this
|
||||
if (!pointerp(data) || len<5) return;
|
||||
|
||||
x=allocate(4);
|
||||
if ((x[0]=data[0])<0) x[0]+=256; // not needed with newer drivers
|
||||
if ((x[1]=data[1])<0) x[1]+=256;
|
||||
if ((x[2]=data[2])<0) x[2]+=256;
|
||||
if ((x[3]=data[3])<0) x[3]+=256;
|
||||
ip_num=sprintf("%d.%d.%d.%d", x[0], x[1], x[2], x[3]);
|
||||
ip_nam=to_string(data[4..]);
|
||||
# ifdef RDNS_DEBUG
|
||||
log_file("IP-NAME", sprintf("got v4: %s -> %s\n", ip_num, ip_nam));
|
||||
# endif
|
||||
|
||||
if (ip_num==ip_nam) return; // not resolved
|
||||
if (!ip_map) ip_map=get_extra_wizinfo(0)[IP_NAMES];
|
||||
ip_map[ip_num, 0]=ip_nam;
|
||||
ip_map[ip_num, 1]=time();
|
||||
}
|
449
mudlib/simul_efun-dr.c
Normal file
449
mudlib/simul_efun-dr.c
Normal file
|
@ -0,0 +1,449 @@
|
|||
/* This is an addition to the simul_efun file for a fast migration from
|
||||
* the -DR parser. Only the ls() function of the original simul_efun need to
|
||||
* be commented out
|
||||
*/
|
||||
#include "/sys/lpctypes.h"
|
||||
#define ATTRIBUTE_INDEX 2
|
||||
#define TEXT_WIDTH 70
|
||||
|
||||
/*
|
||||
* check_ref() is only a fake function.
|
||||
* missing: query_arg/this_arg(), remove_action()
|
||||
*
|
||||
* The following defines might be appropriate when you need to stay with
|
||||
* old code and want speed. Put them in an appropriate header file or in
|
||||
* the auto_include string.
|
||||
*
|
||||
* #define caller() previous_object()
|
||||
* if using OLD_PREVIOUS_OBJECT_BEHAVIOUR :
|
||||
* #define caller() previous_object(0) // always works, but slower
|
||||
*
|
||||
* #define contents(ob) all_inventory((ob))
|
||||
* #define deletem(m, d) efun::m_delete((m), (d))
|
||||
* #define this_verb() query_verb()
|
||||
* #define atoi(str) to_int(str)
|
||||
* #define keys(m) m_indices(m)
|
||||
* #define mapp(m) mappingp(m)
|
||||
*
|
||||
* The following defines have a problem: a parameter is used twice.
|
||||
* #define deletea(a, start, end) ((a)[0..(start)-1] + (a)[(end)+1..])
|
||||
* #define index(a, d, start) member((start) ? (a)[(start)..] : (a) , (d))
|
||||
* #define searcha(a, d, start) member((start) ? (a)[(start)..] : (a) , (d))
|
||||
*/
|
||||
|
||||
static void start_simul_efun_dr() {
|
||||
mixed *info;
|
||||
|
||||
info = get_extra_wizinfo(0);
|
||||
if (!info[ATTRIBUTE_INDEX])
|
||||
info[ATTRIBUTE_INDEX] = allocate_mapping(0, 1);
|
||||
if (find_call_out("clean_simul_efun_dr") < 0)
|
||||
call_out("clean_simul_efun_dr", 900);
|
||||
}
|
||||
|
||||
static void clean_simul_efun_dr() {
|
||||
/* There might be destructed objects as keys. */
|
||||
m_indices(get_extra_wizinfo(0)[ATTRIBUTE_INDEX]);
|
||||
remove_call_out("clean_simul_efun_dr");
|
||||
call_out("clean_simul_efun_dr", 3600);
|
||||
}
|
||||
|
||||
varargs void add_attribute(string name, mixed value, object ob) {
|
||||
mapping attributes;
|
||||
|
||||
if (!ob) {
|
||||
if (objectp(value)) {
|
||||
ob = value;
|
||||
value = 1;
|
||||
} else {
|
||||
ob = previous_object();
|
||||
}
|
||||
}
|
||||
attributes =
|
||||
(attributes = get_extra_wizinfo(0)[ATTRIBUTE_INDEX])[ob] ||
|
||||
(attributes[ob] = allocate_mapping(1, 1));
|
||||
if (member(attributes, quote(name))) {
|
||||
attributes[quote(name)] = value;
|
||||
return;
|
||||
}
|
||||
attributes[name] = value;
|
||||
}
|
||||
|
||||
varargs void add_prot_attribute(string name, mixed value, object ob) {
|
||||
mapping attributes;
|
||||
|
||||
if (!ob) {
|
||||
if (objectp(value)) {
|
||||
ob = value;
|
||||
value = 1;
|
||||
} else {
|
||||
ob = previous_object();
|
||||
}
|
||||
}
|
||||
efun::m_delete(
|
||||
( (attributes = get_extra_wizinfo(0)[ATTRIBUTE_INDEX])[ob] ||
|
||||
(attributes[ob] = allocate_mapping(1, 1)) )
|
||||
, name)[quote(name)] = value;
|
||||
}
|
||||
|
||||
#ifndef caller
|
||||
object caller() {
|
||||
return previous_object(1);
|
||||
}
|
||||
#endif /* caller */
|
||||
|
||||
/* int */ mixed check_ref() {
|
||||
/* There are other ways to debug ref counts. Although a simul_efun is
|
||||
* possible, I doubt that it would be worth the trouble
|
||||
*/
|
||||
return 42.42;
|
||||
}
|
||||
|
||||
object *contents(object ob) {
|
||||
return all_inventory(ob);
|
||||
}
|
||||
|
||||
varargs void delete_attribute(string name, object ob) {
|
||||
mapping attributes;
|
||||
|
||||
if (attributes =
|
||||
get_extra_wizinfo(0)[ATTRIBUTE_INDEX][ob || previous_object()])
|
||||
{
|
||||
if (member(attributes, quote(name)))
|
||||
raise_error(
|
||||
sprintf("Error, cannot delete protected attribute %s.\n", name));
|
||||
if ( !sizeof(efun::m_delete(attributes, name)) )
|
||||
efun::m_delete(
|
||||
get_extra_wizinfo(0)[ATTRIBUTE_INDEX],
|
||||
ob || previous_object()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
varargs mixed deletea(mixed a, int start, int end)
|
||||
{
|
||||
if (!end) /* This isn't really exact; it should */
|
||||
end = start; /* only be done if end is not given. */
|
||||
|
||||
if (end == sizeof(a) - 1) /* Avoid "out of bounds" . */
|
||||
return a[0..start - 1];
|
||||
|
||||
return a[0..start-1] + a[end+1..];
|
||||
}
|
||||
|
||||
mapping deletem(mapping m, mixed d) {
|
||||
return efun::m_delete(m, d);
|
||||
}
|
||||
|
||||
void dumpobjs(int start, int end) {
|
||||
object ob;
|
||||
|
||||
rm("/OBJDUMP");
|
||||
if (end <= 0) {
|
||||
printf("Dumping all objects starting with %d.\n", start);
|
||||
end = 0x7fffffff;
|
||||
} else {
|
||||
printf("Dumping objects %d through %d.\n", start, end);
|
||||
}
|
||||
write_file("/OBJDUMP",
|
||||
sprintf("Object Location\n"));
|
||||
for (ob = debug_info(start); ob && start <= end;
|
||||
ob = debug_info(2, ob), start++)
|
||||
write_file("/OBJDUMP", sprintf("%-40s %s\n", file_name(ob),
|
||||
(environment(ob)?file_name(environment(ob)):"None")));
|
||||
write("Done.\n");
|
||||
}
|
||||
|
||||
int exists(string file) {
|
||||
return file_size(file) != -1;
|
||||
}
|
||||
|
||||
string *files(string path) {
|
||||
mixed *a;
|
||||
string *b;
|
||||
int i, j;
|
||||
|
||||
set_this_object(previous_object());
|
||||
a = get_dir(path, 3);
|
||||
/* Don't call this locally, unless you add code to set this_object() back */
|
||||
b = allocate(j = (i = sizeof(a)) >> 1);
|
||||
while (i)
|
||||
b[--j] = a[--i] < 0 ? a[--i] + "/" : a[--i];
|
||||
return b;
|
||||
}
|
||||
|
||||
string format(string text, int width) {
|
||||
if (width < 0)
|
||||
raise_error("Bad width given to format(); must be >= 0.\n");
|
||||
return sprintf("%*-=s", width || TEXT_WIDTH, text);
|
||||
}
|
||||
|
||||
varargs mixed get_attribute(mixed m, object ob) {
|
||||
mapping attributes;
|
||||
|
||||
if (!stringp(m))
|
||||
return
|
||||
transpose_array( ({
|
||||
m_indices(
|
||||
attributes =
|
||||
get_extra_wizinfo(0)
|
||||
[ATTRIBUTE_INDEX][m || previous_object()] ||
|
||||
allocate_mapping(0,1)),
|
||||
m_values(attributes)
|
||||
}) ) ;
|
||||
if ( ( attributes =
|
||||
get_extra_wizinfo(0)[ATTRIBUTE_INDEX][ob || previous_object()]
|
||||
) && (mapping_contains(&m, attributes, m) ||
|
||||
mapping_contains(&m, attributes, quote(m)))
|
||||
)
|
||||
return m;
|
||||
return -1;
|
||||
}
|
||||
|
||||
varargs string *grab_file(string path, int start, int len) {
|
||||
set_this_object(previous_object());
|
||||
return explode(read_file(path, start, len), "\n");
|
||||
/* Don't call this locally, unless you add code to set this_object() back */
|
||||
}
|
||||
|
||||
int index(mixed a, mixed d, int start) {
|
||||
return member(start ? a[start..] : a , d);
|
||||
}
|
||||
|
||||
string pad(mixed str, int len, int padchar) {
|
||||
string sp_format;
|
||||
|
||||
str = to_string(str);
|
||||
if (len < 0) {
|
||||
if (padchar) {
|
||||
sp_format = "%' '*.*s";
|
||||
sp_format[2] = padchar;
|
||||
return sprintf(sp_format, -len, -len, str);
|
||||
}
|
||||
return sprintf("%*.*s", -len, -len, str);
|
||||
}
|
||||
if (padchar) {
|
||||
sp_format = "%' '-*.*s%s";
|
||||
sp_format[2] = padchar;
|
||||
return sprintf(sp_format, len, len, str, "");
|
||||
}
|
||||
return sprintf("%-*.*s%s", len, len, str, "");
|
||||
}
|
||||
|
||||
varargs void print(string text, int width) {
|
||||
if (width > TEXT_WIDTH)
|
||||
raise_error("Invalid size for argument 2 to print()\n");
|
||||
if (width < 0)
|
||||
raise_error("Bad width given to print(); must be >= 0.\n");
|
||||
write(sprintf("%*-=s", width || TEXT_WIDTH, text));
|
||||
}
|
||||
|
||||
varargs mixed query_attribute(string m, object ob) {
|
||||
mapping attributes;
|
||||
|
||||
return
|
||||
( attributes =
|
||||
get_extra_wizinfo(0)[ATTRIBUTE_INDEX][ob || previous_object()]
|
||||
) && (member(attributes, m) || member(attributes, quote(m)));
|
||||
}
|
||||
|
||||
static int remote_command_flag;
|
||||
int command(string str, object ob) {
|
||||
/* Don't call this locally, unless you add code to set this_object() back */
|
||||
int result;
|
||||
object me;
|
||||
|
||||
if (!ob) {
|
||||
set_this_object(previous_object());
|
||||
return efun::command(str);
|
||||
}
|
||||
if (ob == previous_object()) {
|
||||
set_this_object(previous_object());
|
||||
return efun::command(str);
|
||||
}
|
||||
remote_command_flag++;
|
||||
me = this_object();
|
||||
set_this_object(previous_object());
|
||||
result = efun::command(str, ob);
|
||||
set_this_object(me);
|
||||
remote_command_flag = 0; /* global variable... */
|
||||
return result;
|
||||
}
|
||||
int remote_command() { return remote_command_flag; }
|
||||
|
||||
int root(object ob) {
|
||||
return member(file_name(ob || previous_object()), '#') == -1;
|
||||
}
|
||||
|
||||
int searcha(mixed a, mixed d, int start) {
|
||||
return member(start ? a[start..] : a , d);
|
||||
}
|
||||
|
||||
static private string *strsub_formats = ({0, "\\<%s\\B","\\B%s\\>","\\<%s\\>"});
|
||||
string strsub(string input,string *patterns, int mode) {
|
||||
int i;
|
||||
string format;
|
||||
|
||||
if ( (i = sizeof(patterns)) & 1)
|
||||
raise_error("Odd length array given to strsub.\n");
|
||||
if (!mode) {
|
||||
while (i) {
|
||||
input = implode(explode(input, patterns[<i--]), patterns[<i--]);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
format = strsub_formats[mode];
|
||||
while (i) {
|
||||
input =
|
||||
implode(
|
||||
regexplode(input, sprintf(format, patterns[<i--])),
|
||||
patterns[<i--]
|
||||
);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
string this_verb() { return query_verb(); }
|
||||
|
||||
|
||||
int atoi(string str) { return to_int(str); }
|
||||
|
||||
int cp(string from, string to) {
|
||||
string str;
|
||||
|
||||
set_this_object(previous_object());
|
||||
rm(to);
|
||||
str = read_file(from);
|
||||
write_file(to, str);
|
||||
/* Don't call this locally, unless you add code to set this_object() back */
|
||||
}
|
||||
|
||||
int in_editor(object ob) { return query_editing(ob) && 1; }
|
||||
|
||||
mixed *keys(mapping m) { return m_indices(m); }
|
||||
|
||||
int mapp(mixed m) { return mappingp(m); }
|
||||
|
||||
int memused() {
|
||||
return rusage()[2];
|
||||
}
|
||||
|
||||
object remove_shadow(object ob) {
|
||||
if (!(ob))
|
||||
if ( !(ob = previous_object()) )
|
||||
return 0;
|
||||
/* we are missing a test here to test for actual shadowing. */
|
||||
funcall(bind_lambda(#'unshadow, ob || previous_object()));
|
||||
return ob;
|
||||
}
|
||||
|
||||
mixed *reallocate(mixed *a, int size) {
|
||||
if (size > sizeof(a))
|
||||
return a + allocate(size - sizeof(a));
|
||||
return a[0..size-1];
|
||||
}
|
||||
|
||||
string typeof(mixed m) {
|
||||
switch(efun::typeof(m)) {
|
||||
case T_OBJECT:
|
||||
return "object";
|
||||
case T_NUMBER:
|
||||
return "int";
|
||||
case T_POINTER:
|
||||
return "vector";
|
||||
case T_STRING:
|
||||
return "string";
|
||||
case T_MAPPING:
|
||||
return "mapping";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static int last_destruct;
|
||||
static private mapping destructing = ([]);
|
||||
varargs void destruct(object ob, int flag) {
|
||||
if (flag && !member(destructing, ob)) {
|
||||
if (last_destruct != time())
|
||||
destructing = allocate_mapping(0,0);
|
||||
destructing += ([ob]);
|
||||
ob->destructor();
|
||||
}
|
||||
efun::destruct(ob);
|
||||
}
|
||||
|
||||
/*
|
||||
* The ls() function is no longer needed, as get_dir() can do the same
|
||||
* work.
|
||||
*/
|
||||
void ls(string path) {
|
||||
int max, i, len, tmp;
|
||||
status trunc_flag;
|
||||
mixed *dir;
|
||||
set_this_object(previous_object());
|
||||
if (!path)
|
||||
path = ".";
|
||||
dir = get_dir (path,3);
|
||||
#if defined(COMPAT_FLAG) && 0
|
||||
if (path[0] == '/')
|
||||
path = extract(path, 1);
|
||||
if (path != "")
|
||||
path += "/";
|
||||
#else
|
||||
if (path != "/")
|
||||
path += "/";
|
||||
#endif
|
||||
if (!dir) {
|
||||
write("No such directory.\n");
|
||||
return;
|
||||
}
|
||||
if (sizeof(dir) > 999)
|
||||
{
|
||||
dir = dir[0..998];
|
||||
trunc_flag = 1;
|
||||
}
|
||||
for(i = sizeof(dir); i--; ) {
|
||||
if(dir[i--] == -2)
|
||||
dir[i]+="/";
|
||||
len = strlen(dir[i]);
|
||||
if (len > max)
|
||||
max = len;
|
||||
}
|
||||
++max;
|
||||
if (max > 79)
|
||||
max = 79;
|
||||
for (i=0; i < sizeof(dir); i+=2) {
|
||||
string name;
|
||||
name = dir[i];
|
||||
tmp = strlen(name);
|
||||
if (len + tmp > 79) {
|
||||
len = 0;
|
||||
write("\n");
|
||||
}
|
||||
write(name);
|
||||
if (len + max > 79) {
|
||||
write("\n");
|
||||
len = 0;
|
||||
} else {
|
||||
write(extract(
|
||||
" ",
|
||||
80-max+tmp));
|
||||
len += max;
|
||||
}
|
||||
}
|
||||
write("\n");
|
||||
if (trunc_flag) write("***TRUNCATED***\n");
|
||||
}
|
||||
|
||||
#if 0 /* This is probably too costly; just replace this_player(1) with
|
||||
this_interactive() */
|
||||
/*
|
||||
* Not accurate.
|
||||
* Original behaviour: if arg _supplied_ return current_interactive.
|
||||
*/
|
||||
|
||||
varargs object this_player(int x)
|
||||
{
|
||||
return x ? this_interactive() : efun::this_player();
|
||||
}
|
||||
#endif
|
11
mudlib/sys/comm.h
Normal file
11
mudlib/sys/comm.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef LPC_COMM_H_
|
||||
#define LPC_COMM_H_
|
||||
|
||||
/* Mode values recognized by the efun get_combine_charset()
|
||||
* and get_connection_charset() */
|
||||
|
||||
#define CHARSET_VECTOR 0 /* Return the charset as bitvector array */
|
||||
#define CHARSET_STRING 1 /* Return the charset as string */
|
||||
#define CHARSET_QUOTE_IAC 2 /* Return the status of the IAC quoting */
|
||||
|
||||
#endif /* LPC_COMM_H_ */
|
50
mudlib/sys/commands.h
Normal file
50
mudlib/sys/commands.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#ifndef LPC_COMMANDS_H_
|
||||
#define LPC_COMMANDS_H_
|
||||
|
||||
/* Flags accepted by add_action(fun, verb, flag).
|
||||
* (Below, VERB is what the player enters).
|
||||
* Negative flag values allow VERB to be just the first -<flag>
|
||||
* characters of <verb> (abbreviated verb).
|
||||
*/
|
||||
|
||||
#define AA_VERB 0 /* VERB must be <verb> */
|
||||
#define AA_SHORT 1 /* VERB must start with <verb>,
|
||||
* args do not include extra characters */
|
||||
#define AA_NOSPACE 2 /* VERB must start with <verb>,
|
||||
* args and verb do include extra characters */
|
||||
#define AA_IMM_ARGS 3 /* VERB must start with <verb>,
|
||||
* args do include extra characters */
|
||||
|
||||
/* Bitflags accepted by query_actions(object ob, int mask)
|
||||
*/
|
||||
|
||||
#define QA_VERB 1
|
||||
#define QA_TYPE 2
|
||||
#define QA_SHORT_VERB 4
|
||||
#define QA_OBJECT 8
|
||||
#define QA_FUNCTION 16
|
||||
|
||||
|
||||
/* Indices in the arrays returned from command_stack()
|
||||
*/
|
||||
|
||||
#define CMD_VERB 0
|
||||
#define CMD_TEXT 1
|
||||
#define CMD_ORIGIN 2
|
||||
#define CMD_PLAYER 3
|
||||
#define CMD_FAIL 4
|
||||
#define CMD_FAILOBJ 5
|
||||
|
||||
#define CMD_SIZE 6
|
||||
|
||||
|
||||
/* Indices into the subarrays returned from match_command()
|
||||
*/
|
||||
#define CMDM_VERB 0
|
||||
#define CMDM_ARG 1
|
||||
#define CMDM_OBJECT 2
|
||||
#define CMDM_FUN 3
|
||||
|
||||
#define CMDM_SIZE 4
|
||||
|
||||
#endif /* LPC_COMMANDS_H_ */
|
240
mudlib/sys/debug_info.h
Normal file
240
mudlib/sys/debug_info.h
Normal file
|
@ -0,0 +1,240 @@
|
|||
#ifndef LPC_DEBUG_INFO_H_
|
||||
#define LPC_DEBUG_INFO_H_ 1
|
||||
|
||||
/* Request values for efun debug_info().
|
||||
*/
|
||||
|
||||
#define DINFO_OBJECT 0 /* Print information about an object */
|
||||
#define DINFO_MEMORY 1 /* Print memory usage of an object */
|
||||
#define DINFO_OBJLIST 2 /* Return an object from the global list */
|
||||
#define DINFO_MALLOC 3 /* Print the information from the 'malloc' cmd */
|
||||
#define DINFO_STATUS 4 /* Return the 'status' information */
|
||||
#define DINFO_DUMP 5 /* Dump some special information into files */
|
||||
#define DINFO_DATA 6 /* Return internal information */
|
||||
#define DINFO_TRACE 7 /* Return the current call trace */
|
||||
|
||||
/* Sub-request values for debug_info(DINFO_DATA) */
|
||||
|
||||
#define DID_STATUS 0 /* Return the 'status' and 'status tables' information */
|
||||
#define DID_SWAP 1 /* Return the 'status swap' information */
|
||||
#define DID_MEMORY 2 /* Return the 'status malloc' information */
|
||||
|
||||
/* Sub-request values for debug_info(DINFO_TRACE) */
|
||||
|
||||
#define DIT_CURRENT 0 /* Return the current call chain as an array */
|
||||
#define DIT_ERROR 1 /* Return the last error call chain as an array */
|
||||
#define DIT_UNCAUGHT_ERROR 2 /* Return the last uncaught error call chain */
|
||||
#define DIT_STR_CURRENT 3 /* Return the current call chain as a string */
|
||||
|
||||
/* Indices into the array resulting from debug_info(DINFO_DATA, DID_STATUS)
|
||||
*/
|
||||
|
||||
#define DID_ST_ACTIONS 0
|
||||
#define DID_ST_ACTIONS_SIZE 1
|
||||
#define DID_ST_SHADOWS 2
|
||||
#define DID_ST_SHADOWS_SIZE 3
|
||||
|
||||
#define DID_ST_OBJECTS 4
|
||||
#define DID_ST_OBJECTS_SIZE 5
|
||||
#define DID_ST_OBJECTS_SWAPPED 6
|
||||
#define DID_ST_OBJECTS_SWAP_SIZE 7
|
||||
#define DID_ST_OBJECTS_LIST 8
|
||||
#define DID_ST_OBJECTS_NEWLY_DEST 9
|
||||
#define DID_ST_OBJECTS_DESTRUCTED 10
|
||||
#define DID_ST_OBJECTS_PROCESSED 11
|
||||
#define DID_ST_OBJECTS_AVG_PROC 12
|
||||
|
||||
#define DID_ST_OTABLE 13
|
||||
#define DID_ST_OTABLE_SLOTS 14
|
||||
#define DID_ST_OTABLE_SIZE 15
|
||||
|
||||
#define DID_ST_HBEAT_OBJS 16
|
||||
#define DID_ST_HBEAT_CALLS 17
|
||||
#define DID_ST_HBEAT_CALLS_TOTAL 18
|
||||
#define DID_ST_HBEAT_SLOTS 19
|
||||
#define DID_ST_HBEAT_SIZE 20
|
||||
#define DID_ST_HBEAT_PROCESSED 21
|
||||
#define DID_ST_HBEAT_AVG_PROC 22
|
||||
|
||||
#define DID_ST_CALLOUTS 23
|
||||
#define DID_ST_CALLOUT_SIZE 24
|
||||
|
||||
#define DID_ST_ARRAYS 25
|
||||
#define DID_ST_ARRAYS_SIZE 26
|
||||
|
||||
#define DID_ST_MAPPINGS 27
|
||||
#define DID_ST_MAPPINGS_SIZE 28
|
||||
#define DID_ST_HYBRID_MAPPINGS 51
|
||||
#define DID_ST_HASH_MAPPINGS 54
|
||||
|
||||
#define DID_ST_STRUCTS 29
|
||||
#define DID_ST_STRUCTS_SIZE 30
|
||||
#define DID_ST_STRUCT_TYPES 31
|
||||
#define DID_ST_STRUCT_TYPES_SIZE 32
|
||||
|
||||
#define DID_ST_PROGS 33
|
||||
#define DID_ST_PROGS_SIZE 34
|
||||
|
||||
#define DID_ST_PROGS_SWAPPED 35
|
||||
#define DID_ST_PROGS_SWAP_SIZE 36
|
||||
|
||||
#define DID_ST_USER_RESERVE 37
|
||||
#define DID_ST_MASTER_RESERVE 38
|
||||
#define DID_ST_SYSTEM_RESERVE 39
|
||||
|
||||
#define DID_ST_ADD_MESSAGE 40
|
||||
#define DID_ST_PACKETS 41
|
||||
#define DID_ST_PACKET_SIZE 42
|
||||
#define DID_ST_PACKETS_IN 43
|
||||
#define DID_ST_PACKET_SIZE_IN 44
|
||||
|
||||
#define DID_ST_APPLY 45
|
||||
#define DID_ST_APPLY_HITS 46
|
||||
|
||||
#define DID_ST_STRINGS 47
|
||||
#define DID_ST_STRING_SIZE 48
|
||||
#define DID_ST_STR_TABLE_SIZE 49
|
||||
#define DID_ST_STR_OVERHEAD 50
|
||||
#define DID_ST_UNTABLED 52
|
||||
#define DID_ST_UNTABLED_SIZE 53
|
||||
#define DID_ST_UNUSED54 54 /* UNUSED */
|
||||
#define DID_ST_UNUSED55 55 /* UNUSED */
|
||||
#define DID_ST_TABLED 56
|
||||
#define DID_ST_TABLED_SIZE 57
|
||||
#define DID_ST_STR_SEARCHES 58
|
||||
#define DID_ST_STR_SEARCHLEN 59
|
||||
#define DID_ST_STR_SEARCHES_BYVALUE 60
|
||||
#define DID_ST_STR_SEARCHLEN_BYVALUE 61
|
||||
#define DID_ST_STR_CHAINS 62
|
||||
#define DID_ST_STR_ADDED 63
|
||||
#define DID_ST_STR_DELETED 64
|
||||
#define DID_ST_STR_COLLISIONS 65
|
||||
#define DID_ST_STR_FOUND 66
|
||||
#define DID_ST_STR_FOUND_BYVALUE 67
|
||||
|
||||
#define DID_ST_RX_CACHED 68
|
||||
#define DID_ST_RX_TABLE 69
|
||||
#define DID_ST_RX_TABLE_SIZE 70
|
||||
#define DID_ST_RX_REQUESTS 71
|
||||
#define DID_ST_RX_REQ_FOUND 72
|
||||
#define DID_ST_RX_REQ_COLL 73
|
||||
|
||||
#define DID_ST_MB_FILE 74
|
||||
#define DID_ST_MB_SWAP 75
|
||||
|
||||
#define DID_ST_BOOT_TIME 76
|
||||
|
||||
#define DID_STATUS_MAX 77 /* Total number of entries */
|
||||
|
||||
|
||||
/* Indices into the array resulting from debug_info(DINFO_DATA, DID_SWAP)
|
||||
*/
|
||||
|
||||
#define DID_SW_PROGS 0
|
||||
#define DID_SW_PROG_SIZE 1
|
||||
#define DID_SW_PROG_UNSWAPPED 2
|
||||
#define DID_SW_PROG_U_SIZE 3
|
||||
#define DID_SW_VARS 4
|
||||
#define DID_SW_VAR_SIZE 5
|
||||
#define DID_SW_FREE 6
|
||||
#define DID_SW_FREE_SIZE 7
|
||||
#define DID_SW_FILE_SIZE 8
|
||||
#define DID_SW_REUSED 9
|
||||
#define DID_SW_SEARCHES 10
|
||||
#define DID_SW_SEARCH_LEN 11
|
||||
#define DID_SW_F_SEARCHES 12
|
||||
#define DID_SW_F_SEARCH_LEN 13
|
||||
#define DID_SW_COMPACT 14
|
||||
#define DID_SW_RECYCLE_FREE 15
|
||||
|
||||
#define DID_SWAP_MAX 16
|
||||
|
||||
|
||||
/* Indices into the array resulting from debug_info(DINFO_DATA, DID_MEMORY)
|
||||
*/
|
||||
|
||||
#define DID_MEM_NAME 0
|
||||
#define DID_MEM_SBRK 1
|
||||
#define DID_MEM_SBRK_SIZE 2
|
||||
#define DID_MEM_LARGE 3
|
||||
#define DID_MEM_LARGE_SIZE 4
|
||||
#define DID_MEM_MMAP (DID_MEM_LARGE)
|
||||
#define DID_MEM_MMAP_SIZE (DID_MEM_LARGE_SIZE)
|
||||
#define DID_MEM_LFREE 5
|
||||
#define DID_MEM_FREE_CHUNKS (DID_MEM_LFREE)
|
||||
#define DID_MEM_LFREE_SIZE 6
|
||||
#define DID_MEM_LWASTED 7
|
||||
#define DID_MEM_LWASTED_SIZE 8
|
||||
#define DID_MEM_KEEP_COST (DID_MEM_LWASTED_SIZE)
|
||||
#define DID_MEM_CHUNK 9
|
||||
#define DID_MEM_CHUNK_SIZE 10
|
||||
#define DID_MEM_SLAB (DID_MEM_CHUNK)
|
||||
#define DID_MEM_SLAB_SIZE (DID_MEM_CHUNK_SIZE)
|
||||
#define DID_MEM_MAX_ALLOCATED (DID_MEM_CHUNK_SIZE)
|
||||
#define DID_MEM_SMALL 11
|
||||
#define DID_MEM_SMALL_SIZE 12
|
||||
#define DID_MEM_SFREE 13
|
||||
#define DID_MEM_SFREE_SIZE 14
|
||||
#define DID_MEM_FFREE (DID_MEM_SFREE)
|
||||
#define DID_MEM_FFREE_SIZE (DID_MEM_SFREE_SIZE)
|
||||
#define DID_MEM_SWASTED 15
|
||||
#define DID_MEM_SWASTED_SIZE 16
|
||||
#define DID_MEM_SMALL_OVERHEAD_SIZE (DID_MEM_SWASTED_SIZE)
|
||||
#define DID_MEM_MINC_CALLS 17
|
||||
#define DID_MEM_MINC_SUCCESS 19
|
||||
#define DID_MEM_MINC_SIZE 19
|
||||
#define DID_MEM_PERM 20
|
||||
#define DID_MEM_PERM_SIZE 21
|
||||
#define DID_MEM_CLIB 22
|
||||
#define DID_MEM_CLIB_SIZE 23
|
||||
#define DID_MEM_OVERHEAD 24
|
||||
#define DID_MEM_ALLOCATED 25
|
||||
#define DID_MEM_USED 26
|
||||
#define DID_MEM_TOTAL_UNUSED 27
|
||||
#define DID_MEM_DEFRAG_CALLS 28
|
||||
#define DID_MEM_DEFRAG_CALLS_REQ 29
|
||||
#define DID_MEM_SLAB_FREE (DID_MEM_DEFRAG_CALLS)
|
||||
#define DID_MEM_SLAB_FREE_SIZE (DID_MEM_DEFRAG_CALLS_REQ)
|
||||
#define DID_MEM_DEFRAG_REQ_SUCCESS 30
|
||||
#define DID_MEM_DEFRAG_BLOCKS_INSPECTED 31
|
||||
#define DID_MEM_DEFRAG_BLOCKS_MERGED 32
|
||||
#define DID_MEM_DEFRAG_BLOCKS_RESULT 33
|
||||
#define DID_MEM_AVL_NODES 34
|
||||
#define DID_MEM_EXT_STATISTICS 35
|
||||
|
||||
#define DID_MEMORY_MAX 36
|
||||
|
||||
/* Indices into the subarrays of DID_MEM_EXT_STATISTICS (if given) */
|
||||
|
||||
#define DID_MEM_ES_MAX_ALLOC 0
|
||||
#define DID_MEM_ES_CUR_ALLOC 1
|
||||
#define DID_MEM_ES_MAX_FREE 2
|
||||
#define DID_MEM_ES_CUR_FREE 3
|
||||
#define DID_MEM_ES_AVG_XALLOC 4
|
||||
#define DID_MEM_ES_AVG_XFREE 5
|
||||
#define DID_MEM_ES_FULL_SLABS 6
|
||||
#define DID_MEM_ES_FREE_SLABS 7
|
||||
#define DID_MEM_ES_TOTAL_SLABS 8
|
||||
|
||||
#define DID_MEM_ES_MAX 9
|
||||
|
||||
/* Indices into the subarrays resulting from debug_info(DINFO_TRACE, 0)
|
||||
*/
|
||||
|
||||
#define TRACE_TYPE 0
|
||||
#define TRACE_NAME 1
|
||||
#define TRACE_PROGRAM 2
|
||||
#define TRACE_OBJECT 3
|
||||
#define TRACE_LOC 4
|
||||
|
||||
#define TRACE_MAX 5
|
||||
|
||||
/* Values for entry TRACE_TYPE */
|
||||
|
||||
#define TRACE_TYPE_SYMBOL 0
|
||||
#define TRACE_TYPE_SEFUN 1
|
||||
#define TRACE_TYPE_EFUN 2
|
||||
#define TRACE_TYPE_LAMBDA 3
|
||||
#define TRACE_TYPE_LFUN 4
|
||||
|
||||
#endif /* LPC_DEBUG_INFO_H_ */
|
18
mudlib/sys/debug_message.h
Normal file
18
mudlib/sys/debug_message.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef LPC_DEBUG_MESSAGE_H_
|
||||
#define LPC_DEBUG_MESSAGE_H_ 1
|
||||
|
||||
/* Definitions and macros for the debug_message() */
|
||||
|
||||
#define DMSG_DEFAULT 0 /* log to stdout and .debug.log */
|
||||
#define DMSG_STDOUT (1 << 0) /* log to stdout */
|
||||
#define DMSG_STDERR (1 << 1) /* log to stderr */
|
||||
#define DMSG_LOGFILE (1 << 2) /* log to .debug.log */
|
||||
|
||||
#define DMSG_STAMP (1 << 3) /* Prepend the timestamp */
|
||||
|
||||
/* Derived macros */
|
||||
|
||||
#define DMSG_TARGET (DMSG_STDOUT|DMSG_STDERR|DMSG_LOGFILE)
|
||||
/* Mask for all target bitflags */
|
||||
|
||||
#endif /* LPC_DEBUG_MESSAGE_H_ */
|
35
mudlib/sys/driver_hook.h
Normal file
35
mudlib/sys/driver_hook.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef LPC_DRIVER_HOOK_H_
|
||||
#define LPC_DRIVER_HOOK_H_ 1
|
||||
|
||||
/* --- Driver Hooks ---
|
||||
*/
|
||||
|
||||
#define H_MOVE_OBJECT0 0
|
||||
#define H_MOVE_OBJECT1 1
|
||||
#define H_LOAD_UIDS 2
|
||||
#define H_CLONE_UIDS 3
|
||||
#define H_CREATE_SUPER 4
|
||||
#define H_CREATE_OB 5
|
||||
#define H_CREATE_CLONE 6
|
||||
#define H_RESET 7
|
||||
#define H_CLEAN_UP 8
|
||||
#define H_MODIFY_COMMAND 9
|
||||
#define H_NOTIFY_FAIL 10
|
||||
#define H_NO_IPC_SLOT 11
|
||||
#define H_INCLUDE_DIRS 12
|
||||
#define H_TELNET_NEG 13
|
||||
#define H_NOECHO 14
|
||||
#define H_ERQ_STOP 15
|
||||
#define H_MODIFY_COMMAND_FNAME 16
|
||||
#define H_COMMAND 17
|
||||
#define H_SEND_NOTIFY_FAIL 18
|
||||
#define H_AUTO_INCLUDE 19
|
||||
#define H_DEFAULT_METHOD 20
|
||||
#define H_DEFAULT_PROMPT 21
|
||||
#define H_PRINT_PROMPT 22
|
||||
#define H_REGEXP_PACKAGE 23
|
||||
|
||||
#define NUM_DRIVER_HOOKS 24 /* Number of hooks */
|
||||
|
||||
#endif /* LPC_DRIVER_HOOK_ */
|
||||
|
59
mudlib/sys/erq.h
Normal file
59
mudlib/sys/erq.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* external request demon interface definitions */
|
||||
|
||||
#ifndef LPC__ERQ_H__
|
||||
#define LPC__ERQ_H__ 1
|
||||
|
||||
/* servive request types */
|
||||
|
||||
#define ERQ_RLOOKUP 0 /* Lookup ip -> name */
|
||||
#define ERQ_EXECUTE 1 /* Execute a program */
|
||||
#define ERQ_FORK 2 /* Fork a program */
|
||||
#define ERQ_AUTH 3 /* Connect to a remote authd */
|
||||
#define ERQ_SPAWN 4 /* Spawn a program */
|
||||
#define ERQ_SEND 5 /* Send data to a program or connection */
|
||||
#define ERQ_KILL 6 /* Kill a program or connection */
|
||||
#define ERQ_OPEN_UDP 7 /* Open a UDP socket */
|
||||
#define ERQ_OPEN_TCP 8 /* Open a TCP connection */
|
||||
#define ERQ_LISTEN 9 /* Open a TCP accept-socket */
|
||||
#define ERQ_ACCEPT 10 /* Accept a connection from a accept-socket */
|
||||
#define ERQ_LOOKUP 11 /* Lookup name -> ip */
|
||||
|
||||
#ifdef __IPV6__
|
||||
#define ERQ_RLOOKUPV6 12 /* Lookup name/ip6 */
|
||||
#endif
|
||||
|
||||
/* Additional service request type flags evaluated by efun send_erq().
|
||||
* The ERQ itself won't get to see it.
|
||||
*/
|
||||
|
||||
#define ERQ_CB_STRING (1 << 31) /* Callback closure takes a string arg */
|
||||
|
||||
|
||||
/* answers from ERQ_EXECUTE / ERQ_FORK */
|
||||
|
||||
#define ERQ_OK 0
|
||||
#define ERQ_SIGNALED 1
|
||||
#define ERQ_E_NOTFOUND 2 /* process not found by wait */
|
||||
#define ERQ_E_UNKNOWN 3 /* unknown exit condition from wait() */
|
||||
#define ERQ_E_ARGLENGTH 4
|
||||
#define ERQ_E_ARGFORMAT 5
|
||||
#define ERQ_E_ARGNUMBER 6
|
||||
#define ERQ_E_ILLEGAL 7
|
||||
#define ERQ_E_PATHLEN 8
|
||||
#define ERQ_E_FORKFAIL 9
|
||||
#define ERQ_E_TICKET 11
|
||||
#define ERQ_E_INCOMPLETE 12
|
||||
#define ERQ_E_WOULDBLOCK 13
|
||||
#define ERQ_E_PIPE 14
|
||||
#define ERQ_STDOUT 15 /* Normal data received */
|
||||
#define ERQ_STDERR 16
|
||||
#define ERQ_EXITED 17 /* Connection closed on EOF */
|
||||
#define ERQ_E_NSLOTS 18
|
||||
|
||||
/* reserved handles */
|
||||
|
||||
#define ERQ_HANDLE_RLOOKUP (-1)
|
||||
#define ERQ_HANDLE_KEEP_HANDLE (-2)
|
||||
#define ERQ_HANDLE_RLOOKUPV6 (-3)
|
||||
|
||||
#endif /* LPC__ERQ_H__ */
|
29
mudlib/sys/files.h
Normal file
29
mudlib/sys/files.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef LPC_FILES_H_
|
||||
#define LPC_FILES_H_ 1
|
||||
|
||||
/* Definitions and macros for the various file efuns */
|
||||
|
||||
/* Special return values of file_size() and the size part of get_dir().
|
||||
*/
|
||||
|
||||
#define FSIZE_NOFILE -1 /* File doesn't exist or is not readable */
|
||||
#define FSIZE_DIR -2 /* The file is actually a directory */
|
||||
|
||||
|
||||
/* Flag values for get_dir().
|
||||
*/
|
||||
|
||||
#define GETDIR_EMPTY (0) /* return an empty array (not very useful) */
|
||||
#define GETDIR_NAMES (0x01) /* return the filenames */
|
||||
#define GETDIR_SIZES (0x02) /* return the file sizes */
|
||||
#define GETDIR_DATES (0x04) /* return the dates of last modification */
|
||||
/* (0x08) unused */
|
||||
#define GETDIR_ACCESS (0x40) /* return the dates of last access */
|
||||
#define GETDIR_MODES (0x80) /* return the file mode */
|
||||
|
||||
#define GETDIR_PATH (0x10) /* with _NAMES: add the path to the filenames */
|
||||
#define GETDIR_UNSORTED (0x20) /* return the results unsorted */
|
||||
|
||||
#define GETDIR_ALL (0xDF) /* return all */
|
||||
|
||||
#endif /* LPC_FILES_H_ */
|
69
mudlib/sys/functionlist.h
Normal file
69
mudlib/sys/functionlist.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
#ifndef LPC_FUNCTIONLIST_H
|
||||
#define LPC_FUNCTIONLIST_H
|
||||
|
||||
#ifndef __DRIVER_SOURCE__
|
||||
#include "lpctypes.h"
|
||||
|
||||
#define NAME_INHERITED 0x80000000 /* Defined by inheritance */
|
||||
#define TYPE_MOD_STATIC 0x40000000 /* Static function or variable */
|
||||
#define TYPE_MOD_NO_MASK 0x20000000 /* The nomask => not redefineable */
|
||||
#define TYPE_MOD_PRIVATE 0x10000000 /* Can't be inherited */
|
||||
#define TYPE_MOD_PUBLIC 0x08000000 /* Force inherit through private */
|
||||
#define TYPE_MOD_VARARGS 0x04000000 /* Used for type checking */
|
||||
#define TYPE_MOD_VIRTUAL 0x02000000 /* can be re- and cross- defined */
|
||||
#define TYPE_MOD_PROTECTED 0x01000000 /* cannot be called externally */
|
||||
#define TYPE_MOD_XVARARGS 0x00800000 /* accepts optional arguments */
|
||||
#define TYPE_MOD_NOSAVE TYPE_MOD_STATIC /* vars: can't be saved */
|
||||
/* Internally TYPE_MOD_NOSAVE is 0x00400000, but that never leaves
|
||||
* the compiler.
|
||||
*/
|
||||
#define NAME_CROSS_DEFINED 0x00080000 /* function defined from other program */
|
||||
#if defined(__LPC_STRUCTS__) || defined(USE_STRUCTS)
|
||||
#define NAME_HIDDEN 0x00020000 /* Not visible for inheritance */
|
||||
#define NAME_PROTOTYPE 0x00010000 /* Defined by a prototype only */
|
||||
#define NAME_UNDEFINED 0x00008000 /* Not defined yet */
|
||||
#define NAME_TYPES_LOST 0x00004000 /* inherited, no save_types */
|
||||
#else /* !USE_STRUCTS */
|
||||
#define NAME_HIDDEN 0x00000800 /* Not visible for inheritance */
|
||||
#define NAME_PROTOTYPE 0x00000400 /* Defined by a prototype only */
|
||||
#define NAME_UNDEFINED 0x00000200 /* Not defined yet */
|
||||
#define NAME_TYPES_LOST 0x00000100 /* inherited, no save_types */
|
||||
#endif /* USE_STRUCTS */
|
||||
|
||||
#endif /* !__DRIVER_SOURCE__ */
|
||||
|
||||
|
||||
/* Return value flag types for functionlist() and variable_list() */
|
||||
|
||||
#define RETURN_FUNCTION_NAME 0x01
|
||||
#define RETURN_FUNCTION_FLAGS 0x02
|
||||
#define RETURN_FUNCTION_TYPE 0x04
|
||||
|
||||
|
||||
/* Additional return value flag types for functionlist() */
|
||||
|
||||
#define RETURN_FUNCTION_NUMARG 0x08
|
||||
#define RETURN_FUNCTION_ARGTYPE 0x10 /* not implemented */
|
||||
|
||||
|
||||
/* Additional return value flag types for variable_list() */
|
||||
|
||||
#define RETURN_VARIABLE_VALUE 0x08
|
||||
|
||||
|
||||
/* Masks of the flag unions allowed for various efuns: */
|
||||
#define RETURN_FUNCTION_MASK 0x0f /* functionlist() */
|
||||
#define RETURN_VARIABLE_MASK 0x0f /* variable_list() */
|
||||
|
||||
/* Return value flag types for function_exists() */
|
||||
|
||||
#define FEXISTS_PROGNAME (0)
|
||||
#define FEXISTS_FILENAME (1)
|
||||
#define FEXISTS_LINENO (2)
|
||||
#define FEXISTS_NUMARG (3)
|
||||
#define FEXISTS_TYPE (4)
|
||||
#define FEXISTS_FLAGS (5)
|
||||
|
||||
#define FEXISTS_ALL (3)
|
||||
|
||||
#endif /* LPC_FUNCTIONLIST_H */
|
26
mudlib/sys/idn.h
Normal file
26
mudlib/sys/idn.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef LPC_IDN_H_
|
||||
#define LPC_IDN_H_ 1
|
||||
|
||||
/* --- IDNA Constants ---
|
||||
*/
|
||||
|
||||
/* idna_stringprep() profiles. */
|
||||
|
||||
#define STRINGPREP_NAMEPREP 1
|
||||
#define STRINGPREP_SASLPREP 2
|
||||
#define STRINGPREP_PLAIN 3
|
||||
#define STRINGPREP_TRACE 4
|
||||
#define STRINGPREP_KERBEROS5 5
|
||||
#define STRINGPREP_XMPP_NODEPREP 6
|
||||
#define STRINGPREP_XMPP_RESOURCEPREP 7
|
||||
#define STRINGPREP_ISCSI 8
|
||||
|
||||
/* idna_stringprep() flags */
|
||||
|
||||
#define STRINGPREP_NO_NFKC_FLAG (1<<0)
|
||||
#define STRINGPREP_NO_BIDI_FLAG (1<<1)
|
||||
#define STRINGPREP_NO_UNASSIGNED_FLAG (1<<2)
|
||||
|
||||
#define STRINGPREP_FLAG_MAX (1<<2)
|
||||
|
||||
#endif
|
9
mudlib/sys/include_list.h
Normal file
9
mudlib/sys/include_list.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef LPC_INCLUDE_LIST_H
|
||||
#define LPC_INCLUDE_LIST_H
|
||||
|
||||
/* Return value flag types for include_list() */
|
||||
|
||||
#define INCLIST_FLAT 0x00
|
||||
#define INCLIST_TREE 0x01
|
||||
|
||||
#endif /* LPC_INCLUDE_LIST_H */
|
10
mudlib/sys/inherit_list.h
Normal file
10
mudlib/sys/inherit_list.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef LPC_INHERIT_LIST_H
|
||||
#define LPC_INHERIT_LIST_H
|
||||
|
||||
/* Return value flag types for inherit_list() */
|
||||
|
||||
#define INHLIST_FLAT 0x00
|
||||
#define INHLIST_TREE 0x01
|
||||
#define INHLIST_TAG_VIRTUAL 0x02
|
||||
|
||||
#endif /* LPC_INHERIT_LIST_H */
|
18
mudlib/sys/input_to.h
Normal file
18
mudlib/sys/input_to.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef LPC_INPUT_TO_H_
|
||||
#define LPC_INPUT_TO_H_
|
||||
|
||||
/* Mode values recognized by the efun input_to() */
|
||||
|
||||
#define INPUT_NOECHO 1 /* Don't echo the next line typed */
|
||||
#define INPUT_CHARMODE 2 /* Switch into/out of charmode */
|
||||
#define INPUT_PROMPT 4 /* Use a custom prompt */
|
||||
#define INPUT_NO_TELNET 8 /* Switch into/out of charmode on the driver
|
||||
* side only.
|
||||
*/
|
||||
#define INPUT_APPEND 16 /* Append the input_to to the list of already
|
||||
* pending input_to's.
|
||||
*/
|
||||
/* #define INPUT_BINARY 32 -- nice, but noone has coded it */
|
||||
#define INPUT_IGNORE_BANG 128 /* Disallow the '!' escape */
|
||||
|
||||
#endif /* LPC_INPUT_TO_H_ */
|
68
mudlib/sys/lpctypes.h
Normal file
68
mudlib/sys/lpctypes.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#ifndef LPC_LPCTYPES_H
|
||||
#define LPC_LPCTYPES_H
|
||||
|
||||
/* compile time types, from functionlist() */
|
||||
|
||||
#define TYPE_UNKNOWN 0 /* This type must be casted */
|
||||
#define TYPE_NUMBER 1
|
||||
#define TYPE_STRING 2
|
||||
#define TYPE_VOID 3
|
||||
#define TYPE_OBJECT 4
|
||||
#define TYPE_MAPPING 5
|
||||
#define TYPE_FLOAT 6
|
||||
#define TYPE_ANY 7 /* Will match any type */
|
||||
#define TYPE_CLOSURE 8
|
||||
#define TYPE_SYMBOL 9
|
||||
#define TYPE_QUOTED_ARRAY 10
|
||||
#if defined(USE_STRUCTS) || defined(__LPC_STRUCTS__)
|
||||
#define TYPE_STRUCT 11
|
||||
#endif
|
||||
|
||||
#define TYPE_MOD_POINTER 0x0040 /* Pointer to a basic type */
|
||||
|
||||
/* runtime types, from typeof() */
|
||||
|
||||
#define T_INVALID 0x0
|
||||
#define T_LVALUE 0x1
|
||||
#define T_NUMBER 0x2
|
||||
#define T_STRING 0x3
|
||||
#define T_POINTER 0x4
|
||||
#define T_OBJECT 0x5
|
||||
#define T_MAPPING 0x6
|
||||
#define T_FLOAT 0x7
|
||||
#define T_CLOSURE 0x8
|
||||
#define T_SYMBOL 0x9
|
||||
#define T_QUOTED_ARRAY 0xa
|
||||
#if defined(USE_STRUCTS) || defined(__LPC_STRUCTS__)
|
||||
#define T_STRUCT 0xb
|
||||
#endif
|
||||
|
||||
/* Closure types, stored as secondary type info */
|
||||
|
||||
#ifndef __DRIVER_SOURCE__
|
||||
|
||||
#define CLOSURE_LFUN 0 /* lfun in an object */
|
||||
/* Code 1: currently unused, used to be CLOSURE_ALIEN_LFUN */
|
||||
#define CLOSURE_IDENTIFIER 2 /* variable in this object */
|
||||
#define CLOSURE_PRELIMINARY 3
|
||||
/* Efun closure used in a static initialization */
|
||||
#define CLOSURE_BOUND_LAMBDA 4 /* Bound unbound-lambda closure */
|
||||
#define CLOSURE_LAMBDA 5 /* normal lambda closure */
|
||||
#define CLOSURE_UNBOUND_LAMBDA 6 /* unbound lambda closure. */
|
||||
|
||||
#define CLOSURE_OPERATOR (0xe800)
|
||||
#define CLOSURE_EFUN (0xf000)
|
||||
#define CLOSURE_SIMUL_EFUN (0xf800)
|
||||
|
||||
#define CLOSURE_IS_LFUN(x) (((x)&~1) == 0)
|
||||
#define CLOSURE_IS_IDENTIFIER(x) ((x) == CLOSURE_IDENTIFIER)
|
||||
#define CLOSURE_IS_BOUND_LAMBDA(x) ((x) == CLOSURE_BOUND_LAMBDA)
|
||||
#define CLOSURE_IS_LAMBDA(x) ((x) == CLOSURE_LAMBDA)
|
||||
#define CLOSURE_IS_UNBOUND_LAMBDA(x) ((x) == CLOSURE_UNBOUND_LAMBDA)
|
||||
#define CLOSURE_IS_SIMUL_EFUN(x) (((x) & 0xf800) == CLOSURE_SIMUL_EFUN)
|
||||
#define CLOSURE_IS_EFUN(x) (((x) & 0xf800) == CLOSURE_EFUN)
|
||||
#define CLOSURE_IS_OPERATOR(x) (((x) & 0xf800) == CLOSURE_OPERATOR)
|
||||
|
||||
#endif /* __DRIVER_SOURCE__ */
|
||||
|
||||
#endif /* LPC_LPCTYPES_H */
|
83
mudlib/sys/objectinfo.h
Normal file
83
mudlib/sys/objectinfo.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
#ifndef LPC_OBJECTINFO_H_
|
||||
#define LPC_OBJECTINFO_H_
|
||||
|
||||
/* Definition of argument values for object_info() and
|
||||
* of the indices in the corresponding result arrays.
|
||||
*/
|
||||
|
||||
/* Possible types of information requested from object_info()
|
||||
*/
|
||||
#define OINFO_BASIC 0
|
||||
#define OINFO_POSITION 1
|
||||
#define OINFO_MEMORY 2
|
||||
|
||||
|
||||
/* Indices in the array resulting from OINFO_BASIC
|
||||
*/
|
||||
|
||||
#define OIB_HEART_BEAT 0
|
||||
#define OIB_IS_WIZARD 1
|
||||
#define OIB_ENABLE_COMMANDS 2
|
||||
#define OIB_CLONE 3
|
||||
#define OIB_DESTRUCTED 4
|
||||
#define OIB_SWAPPED 5
|
||||
#define OIB_ONCE_INTERACTIVE 6
|
||||
#define OIB_RESET_STATE 7
|
||||
#define OIB_WILL_CLEAN_UP 8
|
||||
#define OIB_LAMBDA_REFERENCED 9
|
||||
#define OIB_SHADOW 10
|
||||
#define OIB_REPLACED 11
|
||||
#define OIB_TOTAL_LIGHT 12
|
||||
#define OIB_NEXT_RESET 13
|
||||
#define OIB_TIME_OF_REF 14
|
||||
#define OIB_REF 15
|
||||
#define OIB_GIGATICKS 16
|
||||
#define OIB_TICKS 17
|
||||
#define OIB_SWAP_NUM 18
|
||||
#define OIB_PROG_SWAPPED 19
|
||||
#define OIB_VAR_SWAPPED 20
|
||||
#define OIB_NAME 21
|
||||
#define OIB_LOAD_NAME 22
|
||||
#define OIB_NEXT_ALL 23
|
||||
#define OIB_PREV_ALL 24
|
||||
#define OIB_NEXT_CLEANUP 25
|
||||
|
||||
#define OIB_MAX 26 /* Number of OIB_ result elements */
|
||||
|
||||
|
||||
/* Indices in the array resulting from OINFO_POSITION
|
||||
*/
|
||||
#define OIP_NEXT 0
|
||||
#define OIP_PREV 1
|
||||
#define OIP_POS 2
|
||||
|
||||
#define OIP_MAX 3 /* Number of OIP_ result elements */
|
||||
|
||||
|
||||
/* Indices in the array resulting from OINFO_MEMORY
|
||||
*/
|
||||
#define OIM_REF 0
|
||||
#define OIM_NAME 1
|
||||
#define OIM_PROG_SIZE 2
|
||||
#define OIM_NUM_FUNCTIONS 3
|
||||
#define OIM_SIZE_FUNCTIONS 4
|
||||
#define OIM_NUM_VARIABLES 5
|
||||
#define OIM_SIZE_VARIABLES 6
|
||||
#define OIM_NUM_STRINGS 7
|
||||
#define OIM_SIZE_STRINGS 8
|
||||
#define OIM_SIZE_STRINGS_DATA 9
|
||||
#define OIM_SIZE_STRINGS_TOTAL 10
|
||||
#define OIM_NUM_INHERITED 11
|
||||
#define OIM_SIZE_INHERITED 12
|
||||
#define OIM_TOTAL_SIZE 13
|
||||
#define OIM_DATA_SIZE 14
|
||||
#define OIM_TOTAL_DATA_SIZE 15
|
||||
#define OIM_NO_INHERIT 16
|
||||
#define OIM_NO_CLONE 17
|
||||
#define OIM_NO_SHADOW 18
|
||||
#define OIM_NUM_INCLUDES 19
|
||||
#define OIM_SHARE_VARIABLES 20
|
||||
|
||||
#define OIM_MAX 21 /* Number of OIM_ result elements */
|
||||
|
||||
#endif /* LPC_OBJECTINFO_H_ */
|
23
mudlib/sys/pgsql.h
Normal file
23
mudlib/sys/pgsql.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef _PGSQL_H
|
||||
#define _PGSQL_H
|
||||
|
||||
/* Definitions for the PostgreSQL efuns */
|
||||
|
||||
#define PGRES_EMPTY_QUERY 0 /* Unimplemented */
|
||||
#define PGRES_COMMAND_OK 1
|
||||
#define PGRES_TUPLES_OK 2
|
||||
#define PGRES_COPY_OUT 3 /* Unimplemented */
|
||||
#define PGRES_COPY_IN 4 /* Unimplemented */
|
||||
#define PGRES_BAD_RESPONSE 5
|
||||
#define PGRES_NONFATAL_ERROR 6
|
||||
#define PGRES_FATAL_ERROR 7
|
||||
#define PGRES_NOTICE 99
|
||||
|
||||
#define PGCONN_SUCCESS 100
|
||||
#define PGCONN_FAILED 101
|
||||
#define PGCONN_ABORTED 102
|
||||
|
||||
#define PG_RESULT_ARRAY 0
|
||||
#define PG_RESULT_MAP 1
|
||||
|
||||
#endif
|
43
mudlib/sys/regexp.h
Normal file
43
mudlib/sys/regexp.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef LPC_REGEXP_H_
|
||||
#define LPC_REGEXP_H_ 1
|
||||
|
||||
/* Definitions of regexp option values */
|
||||
|
||||
/* Not really an RE option, but used in conjunction with some RE functions: */
|
||||
|
||||
#define RE_GLOBAL 0x0001 /* Apply RE globally (if possible) */
|
||||
|
||||
/* Options supported by the old regexp package: */
|
||||
|
||||
#define RE_EXCOMPATIBLE 0x0002 /* RE is compatible with ex */
|
||||
|
||||
/* Options supported by the PCRE regexp package: */
|
||||
|
||||
#define RE_CASELESS 0x0004
|
||||
#define RE_MULTILINE 0x0008
|
||||
#define RE_DOTALL 0x0010
|
||||
#define RE_EXTENDED 0x0020
|
||||
#define RE_ANCHORED 0x0040
|
||||
#define RE_DOLLAR_ENDONLY 0x0080
|
||||
#define RE_NOTBOL 0x0100
|
||||
#define RE_NOTEOL 0x0200
|
||||
#define RE_UNGREEDY 0x0400
|
||||
#define RE_NOTEMPTY 0x0800
|
||||
#define RE_UTF8 0x1000
|
||||
|
||||
/* Options specific for regmatch(): */
|
||||
|
||||
#define RE_MATCH_SUBS 0x00100000 /* Return matched subexpressions */
|
||||
|
||||
/* Options specific for regexplode(): */
|
||||
|
||||
#define RE_OMIT_DELIM 0x00100000 /* Omit the delimiters */
|
||||
|
||||
/* Regexp package selection options: */
|
||||
|
||||
#define RE_TRADITIONAL 0x04000000
|
||||
#define RE_PCRE 0x02000000
|
||||
|
||||
#define RE_PACKAGE_MASK (RE_TRADITIONAL | RE_PCRE)
|
||||
|
||||
#endif /* LPC_REGEXP_H_ */
|
24
mudlib/sys/rtlimits.h
Normal file
24
mudlib/sys/rtlimits.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef LPC_RTLIMITS_H_
|
||||
#define LPC_RTLIMITS_H_
|
||||
|
||||
/* Runtime limit index/tag values */
|
||||
|
||||
#define LIMIT_EVAL (0)
|
||||
#define LIMIT_ARRAY (1)
|
||||
#define LIMIT_MAPPING (2)
|
||||
#define LIMIT_MAPPING_KEYS LIMIT_MAPPING
|
||||
#define LIMIT_MAPPING_SIZE (3)
|
||||
#define LIMIT_BYTE (4)
|
||||
#define LIMIT_FILE (5)
|
||||
#define LIMIT_CALLOUTS (6)
|
||||
#define LIMIT_COST (7)
|
||||
|
||||
#define LIMIT_MAX (8) /* Number of recognized limits */
|
||||
|
||||
/* Special limit values */
|
||||
|
||||
#define LIMIT_UNLIMITED 0 /* No limit */
|
||||
#define LIMIT_KEEP (-1) /* Keep the old limit setting */
|
||||
#define LIMIT_DEFAULT (-2) /* Use the default setting */
|
||||
|
||||
#endif /* LPC_RTLIMITS_H_ */
|
10
mudlib/sys/sent.h
Normal file
10
mudlib/sys/sent.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef LPC_SENT_H_
|
||||
#define LPC_SENT_H_
|
||||
|
||||
#define SENT_PLAIN 0
|
||||
#define SENT_SHORT_VERB 1
|
||||
#define SENT_NO_SPACE 2
|
||||
#define SENT_NO_VERB 3
|
||||
#define SENT_MARKER 4
|
||||
|
||||
#endif
|
10
mudlib/sys/strings.h
Normal file
10
mudlib/sys/strings.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef LPC_STRINGS_H_
|
||||
#define LPC_STRINGS_H_ 1
|
||||
|
||||
/* 'where' argument values for trim() */
|
||||
|
||||
#define TRIM_LEFT 0x01
|
||||
#define TRIM_RIGHT 0x02
|
||||
#define TRIM_BOTH (TRIM_LEFT|TRIM_RIGHT)
|
||||
|
||||
#endif /* LPC_STRINGS_H_ */
|
38
mudlib/sys/struct_info.h
Normal file
38
mudlib/sys/struct_info.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef LPC_STRUCTINFO_H_
|
||||
#define LPC_STRUCTINFO_H_
|
||||
|
||||
#ifndef __DRIVER_SOURCE__
|
||||
#include "lpctypes.h"
|
||||
#endif
|
||||
|
||||
/* Definition of argument values for struct_info() and
|
||||
* of the indices in the corresponding result arrays.
|
||||
*/
|
||||
|
||||
/* Possible types of information requested from struct_info()
|
||||
*/
|
||||
#define SINFO_FLAT 0
|
||||
#define SINFO_NESTED 1
|
||||
|
||||
|
||||
/* Indices in the result array
|
||||
*/
|
||||
|
||||
#define SI_NAME 0
|
||||
#define SI_PROG_NAME 1
|
||||
#define SI_PROG_ID 2
|
||||
#define SI_BASE 3
|
||||
#define SI_MEMBER 4
|
||||
|
||||
#define SI_MAX 5 /* Min Number of SI_ result elements */
|
||||
|
||||
/* Indices in the SI_MEMBER arrays
|
||||
*/
|
||||
|
||||
#define SIM_NAME 0
|
||||
#define SIM_TYPE 1
|
||||
#define SIM_EXTRA 2
|
||||
|
||||
#define SIM_MAX 3 /* Number of SIM_ elements */
|
||||
|
||||
#endif /* LPC_STRUCTINFO_H_ */
|
217
mudlib/sys/telnet.h
Normal file
217
mudlib/sys/telnet.h
Normal file
|
@ -0,0 +1,217 @@
|
|||
#ifndef TELNET_H__
|
||||
#define TELNET_H__ 1
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* @(#)telnet.h 5.7 (Berkeley) 11/14/89
|
||||
*/
|
||||
|
||||
/*
|
||||
* Definitions for the TELNET protocol.
|
||||
*/
|
||||
#define IAC 255 /* interpret as command: */
|
||||
#define DONT 254 /* you are not to use option */
|
||||
#define DO 253 /* please, you use option */
|
||||
#define WONT 252 /* I won't use option */
|
||||
#define WILL 251 /* I will use option */
|
||||
#define SB 250 /* interpret as subnegotiation */
|
||||
#define GA 249 /* you may reverse the line */
|
||||
#define EL 248 /* erase the current line */
|
||||
#define EC 247 /* erase the current character */
|
||||
#define AYT 246 /* are you there */
|
||||
#define AO 245 /* abort output--but let prog finish */
|
||||
#define IP 244 /* interrupt process--permanently */
|
||||
#define BREAK 243 /* break */
|
||||
#define DM 242 /* data mark--for connect. cleaning */
|
||||
#define NOP 241 /* nop */
|
||||
#define SE 240 /* end sub negotiation */
|
||||
#define EOR 239 /* end of record (transparent mode) */
|
||||
#define ABORT 238 /* Abort process */
|
||||
#define SUSP 237 /* Suspend process */
|
||||
#define xEOF 236 /* End of file: EOF is already used... */
|
||||
|
||||
#define SYNCH 242 /* for telfunc calls */
|
||||
|
||||
#ifdef __DRIVER_SOURCE__
|
||||
|
||||
#ifdef TELCMDS
|
||||
char *telcmds[] = {
|
||||
"EOF", "SUSP", "ABORT", "EOR",
|
||||
"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
|
||||
"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC",
|
||||
};
|
||||
#define TELCMD_FIRST xEOF
|
||||
#define TELCMD_LAST IAC
|
||||
#define TELCMD_OK(x) ((x) <= TELCMD_LAST && (x) >= TELCMD_FIRST)
|
||||
#define TELCMD(x) telcmds[(x)-TELCMD_FIRST]
|
||||
#endif
|
||||
|
||||
#endif /* __DRIVER_SOURCE__ */
|
||||
|
||||
/* telnet options */
|
||||
#define TELOPT_BINARY 0 /* 8-bit data path */
|
||||
#define TELOPT_ECHO 1 /* echo */
|
||||
#define TELOPT_RCP 2 /* prepare to reconnect */
|
||||
#define TELOPT_SGA 3 /* suppress go ahead */
|
||||
#define TELOPT_NAMS 4 /* approximate message size */
|
||||
#define TELOPT_STATUS 5 /* give status */
|
||||
#define TELOPT_TM 6 /* timing mark */
|
||||
#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
|
||||
#define TELOPT_NAOL 8 /* negotiate about output line width */
|
||||
#define TELOPT_NAOP 9 /* negotiate about output page size */
|
||||
#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
|
||||
#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
|
||||
#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
|
||||
#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
|
||||
#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
|
||||
#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
|
||||
#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
|
||||
#define TELOPT_XASCII 17 /* extended ascic character set */
|
||||
#define TELOPT_LOGOUT 18 /* force logout */
|
||||
#define TELOPT_BM 19 /* byte macro */
|
||||
#define TELOPT_DET 20 /* data entry terminal */
|
||||
#define TELOPT_SUPDUP 21 /* supdup protocol */
|
||||
#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
|
||||
#define TELOPT_SNDLOC 23 /* send location */
|
||||
#define TELOPT_TTYPE 24 /* terminal type */
|
||||
#define TELOPT_EOR 25 /* end or record */
|
||||
#define TELOPT_TUID 26 /* TACACS user identification */
|
||||
#define TELOPT_OUTMRK 27 /* output marking */
|
||||
#define TELOPT_TTYLOC 28 /* terminal location number */
|
||||
#define TELOPT_3270REGIME 29 /* 3270 regime */
|
||||
#define TELOPT_X3PAD 30 /* X.3 PAD */
|
||||
#define TELOPT_NAWS 31 /* window size */
|
||||
#define TELOPT_TSPEED 32 /* terminal speed */
|
||||
#define TELOPT_LFLOW 33 /* remote flow control */
|
||||
#define TELOPT_LINEMODE 34 /* Linemode option */
|
||||
#define TELOPT_XDISPLOC 35 /* X Display Location */
|
||||
#define TELOPT_ENVIRON 36 /* Environment opt for Port ID */
|
||||
#define TELOPT_AUTHENTICATION 37 /* authentication */
|
||||
#define TELOPT_ENCRYPT 38 /* authentication */
|
||||
#define TELOPT_NEWENV 39 /* Environment opt for Port ID */
|
||||
#define TELOPT_STARTTLS 46 /* Transport Layer Security */
|
||||
|
||||
/* Inofficial, mud specific telnet options */
|
||||
#define TELOPT_COMPRESS 85 /* Mud Compression Protocol, v.1 */
|
||||
#define TELOPT_COMPRESS2 86 /* Mud Compression Protocol, v.2 */
|
||||
#define TELOPT_MSP 90 /* Mud Sound Protocol */
|
||||
#define TELOPT_MXP 91 /* Mud Extension Protocol */
|
||||
#define TELOPT_EXOPL 255 /* extended-options-list */
|
||||
|
||||
#define NTELOPTS 256 /* was: (1+TELOPT_NEWENV) */
|
||||
|
||||
#ifdef __DRIVER_SOURCE__
|
||||
|
||||
#ifdef TELOPTS
|
||||
char *telopts[NTELOPTS]
|
||||
= { "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD"
|
||||
, "NAME", "STATUS", "TIMING MARK", "RCTE"
|
||||
, "NAOL", "NAOP", "NAOCRD", "NAOHTS"
|
||||
, "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD"
|
||||
, "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO"
|
||||
, "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION"
|
||||
, "TERMINAL TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING"
|
||||
, "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS"
|
||||
, "TSPEED", "LFLOW", "LINEMODE", "XDISPLOC"
|
||||
, "ENVIRON", "AUTH", "ENCRYPT", "NEWENV"
|
||||
, "TELOPT 40", "TELOPT 41", "TELOPT 42", "TELOPT 43"
|
||||
, "TELOPT 44", "TELOPT 45", "STARTTLS", "TELOPT 47"
|
||||
, "TELOPT 48", "TELOPT 49", "TELOPT 50", "TELOPT 51"
|
||||
, "TELOPT 52", "TELOPT 53", "TELOPT 54", "TELOPT 55"
|
||||
, "TELOPT 56", "TELOPT 57", "TELOPT 58", "TELOPT 59"
|
||||
, "TELOPT 60", "TELOPT 61", "TELOPT 62", "TELOPT 63"
|
||||
, "TELOPT 64", "TELOPT 65", "TELOPT 66", "TELOPT 67"
|
||||
, "TELOPT 68", "TELOPT 69", "TELOPT 70", "TELOPT 71"
|
||||
, "TELOPT 72", "TELOPT 73", "TELOPT 74", "TELOPT 75"
|
||||
, "TELOPT 76", "TELOPT 77", "TELOPT 78", "TELOPT 79"
|
||||
, "TELOPT 80", "TELOPT 81", "TELOPT 82", "TELOPT 83"
|
||||
, "TELOPT 84", "MUD COMPRESS", "MUD COMPRESS2", "TELOPT 87"
|
||||
, "TELOPT 88", "TELOPT 89", "MUD SOUND", "MUD EXTENSION"
|
||||
};
|
||||
#define TELOPT_FIRST TELOPT_BINARY
|
||||
#define TELOPT_LAST TELOPT_MXP
|
||||
#define TELOPT_OK(x) ((x) <= TELOPT_LAST && (x) >= TELOPT_FIRST)
|
||||
#define TELOPT(x) telopts[(x)-TELOPT_FIRST]
|
||||
#endif
|
||||
|
||||
#endif /* __DRIVER_SOURCE__ */
|
||||
|
||||
/* sub-option qualifiers */
|
||||
#define TELQUAL_IS 0 /* option is... */
|
||||
#define TELQUAL_SEND 1 /* send option */
|
||||
|
||||
/*
|
||||
* LINEMODE suboptions
|
||||
*/
|
||||
|
||||
#define LM_MODE 1
|
||||
#define LM_FORWARDMASK 2
|
||||
#define LM_SLC 3
|
||||
|
||||
#define MODE_EDIT 0x01
|
||||
#define MODE_TRAPSIG 0x02
|
||||
#define MODE_ACK 0x04
|
||||
|
||||
#define MODE_MASK (MODE_EDIT|MODE_TRAPSIG|MODE_ACK)
|
||||
|
||||
/* Not part of protocol, but needed to simplify things... */
|
||||
#define MODE_FLOW 0x0100
|
||||
#define MODE_ECHO 0x0200
|
||||
#define MODE_INBIN 0x0400
|
||||
#define MODE_OUTBIN 0x0800
|
||||
#define MODE_FORCE 0x1000
|
||||
|
||||
#define SLC_SYNCH 1
|
||||
#define SLC_BRK 2
|
||||
#define SLC_IP 3
|
||||
#define SLC_AO 4
|
||||
#define SLC_AYT 5
|
||||
#define SLC_EOR 6
|
||||
#define SLC_ABORT 7
|
||||
#define SLC_EOF 8
|
||||
#define SLC_SUSP 9
|
||||
#define SLC_EC 10
|
||||
#define SLC_EL 11
|
||||
#define SLC_EW 12
|
||||
#define SLC_RP 13
|
||||
#define SLC_LNEXT 14
|
||||
#define SLC_XON 15
|
||||
#define SLC_XOFF 16
|
||||
#define SLC_FORW1 17
|
||||
#define SLC_FORW2 18
|
||||
|
||||
#define NSLC 18
|
||||
|
||||
#define SLC_NAMES "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
|
||||
"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
|
||||
"LNEXT", "XON", "XOFF", "FORW1", "FORW2"
|
||||
|
||||
#define SLC_NOSUPPORT 0
|
||||
#define SLC_CANTCHANGE 1
|
||||
#define SLC_VARIABLE 2
|
||||
#define SLC_DEFAULT 3
|
||||
#define SLC_LEVELBITS 0x03
|
||||
|
||||
#define SLC_FUNC 0
|
||||
#define SLC_FLAGS 1
|
||||
#define SLC_VALUE 2
|
||||
|
||||
#define SLC_ACK 0x80
|
||||
#define SLC_FLUSHIN 0x40
|
||||
#define SLC_FLUSHOUT 0x20
|
||||
|
||||
#endif /* TELNET_H__ */
|
18
mudlib/sys/time.h
Normal file
18
mudlib/sys/time.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef LPC_TIME_H_
|
||||
#define LPC_TIME_H_ 1
|
||||
|
||||
/* Indices into the array returned from gmtime() and localtime(). */
|
||||
|
||||
#define TM_SEC 0 /* Seconds (0..59) */
|
||||
#define TM_MIN 1 /* Minutes (0..59) */
|
||||
#define TM_HOUR 2 /* Hours (0..23) */
|
||||
#define TM_MDAY 3 /* Day of the month (1..31) */
|
||||
#define TM_MON 4 /* Month of the year (0..11) */
|
||||
#define TM_YEAR 5 /* Year (e.g. 2001) */
|
||||
#define TM_WDAY 6 /* Day of the week (Sunday = 0) */
|
||||
#define TM_YDAY 7 /* Day of the year (0..365) */
|
||||
#define TM_ISDST 8 /* TRUE: Daylight saving time */
|
||||
|
||||
#define TM_MAX 9 /* Number of entries in the array */
|
||||
|
||||
#endif /* LPC_TIME_H_ */
|
87
mudlib/sys/tls.h
Normal file
87
mudlib/sys/tls.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
#ifndef LPC_TLS_H
|
||||
#define LPC_TLS_H
|
||||
|
||||
/* Field indices for the result of tls_query_connection_info() */
|
||||
|
||||
#define TLS_CIPHER 0
|
||||
#define TLS_COMP 1
|
||||
#define TLS_KX 2
|
||||
#define TLS_MAC 3
|
||||
#define TLS_PROT 4
|
||||
#define TLS_SESSION 5
|
||||
|
||||
#define TLS_INFO_MAX 6 /* Total number of result fields */
|
||||
|
||||
/* Interpretation of the cipher information */
|
||||
|
||||
#define TLS_CIPHER_TABLE ({ \
|
||||
"TLS_CIPHER_NONE", \
|
||||
"TLS_CIPHER_NULL", \
|
||||
"TLS_CIPHER_ARCFOUR_128", \
|
||||
"TLS_CIPHER_3DES_CBC", \
|
||||
"TLS_CIPHER_RIJNDAEL_128_CBC", \
|
||||
"TLS_CIPHER_RIJNDAEL_256_CBC", \
|
||||
"TLS_CIPHER_ARCFOUR_40" \
|
||||
})
|
||||
|
||||
#define TLS_CIPHER_NAME(x) TLS_CIPHER_TABLE[(x)]
|
||||
|
||||
/* Interpretation of the key-exchange information */
|
||||
|
||||
#define TLS_KX_TABLE ({ \
|
||||
"TLS_KX_NONE", \
|
||||
"TLS_KX_RSA", \
|
||||
"TLS_KX_DHE_DSS", \
|
||||
"TLS_KX_DHE_RSA", \
|
||||
"TLS_KX_ANON_DH", \
|
||||
"TLS_KX_SRP", \
|
||||
"TLS_KX_RSA_EXPORT", \
|
||||
"TLS_KX_SRP_RSA", \
|
||||
"TLS_KX_SRP_DSS" \
|
||||
})
|
||||
|
||||
#define TLS_KX_NAME(x) TLS_KX_TABLE[(x)]
|
||||
|
||||
/* Interpretation of the MAC information */
|
||||
|
||||
#define TLS_MAC_TABLE ({ \
|
||||
"TLS_MAC_NONE", \
|
||||
"TLS_MAC_NULL", \
|
||||
"TLS_MAC_MD5", \
|
||||
"TLS_MAC_SHA" \
|
||||
})
|
||||
|
||||
#define TLS_MAC_NAME(x) TLS_MAC_TABLE[(x)]
|
||||
|
||||
/* Interpretation of the compression information */
|
||||
|
||||
#define TLS_COMP_TABLE ({ \
|
||||
"TLS_COMP_NONE", \
|
||||
"TLS_COMP_NULL", \
|
||||
"TLS_COMP_ZLIB", \
|
||||
"TLS_COMP_LZO" \
|
||||
})
|
||||
|
||||
#define TLS_COMP_NAME(x) TLS_COMP_TABLE[(x)]
|
||||
|
||||
/* Interpretation of the protocol information */
|
||||
|
||||
#define TLS_PROT_TABLE ({ \
|
||||
"TLS_PROT_NONE", \
|
||||
"TLS_PROT_SSL3", \
|
||||
"TLS_PROT_TLS1" \
|
||||
})
|
||||
|
||||
#define TLS_PROT_NAME(x) TLS_PROT_TABLE[(x)]
|
||||
|
||||
/* Recognized hash() algorithms (not all may be supported at runtime) */
|
||||
|
||||
#define TLS_HASH_SHA1 (1)
|
||||
#define TLS_HASH_SHA224 (2)
|
||||
#define TLS_HASH_SHA256 (3)
|
||||
#define TLS_HASH_SHA384 (4)
|
||||
#define TLS_HASH_SHA512 (5)
|
||||
#define TLS_HASH_MD5 (6)
|
||||
#define TLS_HASH_RIPEMD160 (7)
|
||||
|
||||
#endif /* LPC_TLS_H */
|
18
mudlib/sys/trace.h
Normal file
18
mudlib/sys/trace.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef LPC_TRACE_H_
|
||||
#define LPC_TRACE_H_
|
||||
|
||||
/* Argument values for the trace() efun.
|
||||
*/
|
||||
|
||||
#define TRACE_NOTHING 0 /* Stop tracing */
|
||||
|
||||
#define TRACE_CALL 1 /* Trace all lfun calls */
|
||||
#define TRACE_CALL_OTHER 2 /* Trace inter-object calls */
|
||||
#define TRACE_RETURN 4 /* Trace function returns */
|
||||
#define TRACE_ARGS 8 /* Print function arguments and results */
|
||||
#define TRACE_EXEC 16 /* Trace all executed instructions */
|
||||
#define TRACE_HEART_BEAT 32 /* Trace heartbeat code */
|
||||
#define TRACE_APPLY 64 /* Trace (internal) applies */
|
||||
#define TRACE_OBJNAME 128 /* Print the object names */
|
||||
|
||||
#endif /* LPC_TRACE_H_ */
|
22
mudlib/sys/wizlist.h
Normal file
22
mudlib/sys/wizlist.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef LPC_WIZLIST_H_
|
||||
#define LPC_WIZLIST_H_ 1
|
||||
|
||||
/* Indices returned by wizlist_info()
|
||||
*/
|
||||
|
||||
#define WL_NAME 0 /* Wizard name */
|
||||
#define WL_COMMANDS 1 /* Number of commands executed */
|
||||
#define WL_COST 2 /* Weighted evalcost spent on this wizard */
|
||||
#define WL_GIGACOST 3 /* Weighted giga-evalcost spent on this wizard */
|
||||
#define WL_TOTAL_COST 4 /* Total evalcost spent on this wizard */
|
||||
#define WL_TOTAL_GIGACOST 5 /* Total giga-evalcost spent on this wizard */
|
||||
#define WL_HEART_BEATS 6 /* Heartbeats spent on this wizard */
|
||||
#define WL_CALL_OUT 7 /* unimplemented */
|
||||
#define WL_ARRAY_TOTAL 8 /* Arrays accounted for */
|
||||
#define WL_MAPPING_TOTAL 9 /* Mappings accounted for */
|
||||
#define WL_STRUCT_TOTAL 10 /* Struct elements accounted for */
|
||||
#define WL_EXTRA 11 /* Extra Wizinfo, if set */
|
||||
|
||||
#define WL_SIZE 12 /* Number of entries */
|
||||
|
||||
#endif /* LPC_WIZLIST_H_ */
|
1247
mudlib/telnetneg.c
Normal file
1247
mudlib/telnetneg.c
Normal file
File diff suppressed because it is too large
Load diff
277
mudlib/telnetneg.h
Normal file
277
mudlib/telnetneg.h
Normal file
|
@ -0,0 +1,277 @@
|
|||
//
|
||||
// Wunderland Mudlib
|
||||
//
|
||||
// telnet.h -- Standard telnet definitions
|
||||
//
|
||||
// $Log: telnetneg.h,v $
|
||||
// Revision 1.1.1.1 2006/07/10 02:42:09 lynx
|
||||
// ldmud 3.3.714
|
||||
//
|
||||
// Revision 1.10 2002/12/02 17:31:56 Fiona
|
||||
// sb_ttype und sb_xdisp
|
||||
//
|
||||
|
||||
#ifndef __TELNET_H__
|
||||
#define __TELNET_H__
|
||||
|
||||
// ******************** Telnet State Machine ********************
|
||||
|
||||
// Each option could be in one of the following four states. There
|
||||
// is also a one element queue for each option. Mind that each option
|
||||
// could have different states for the lokal and the remote system.
|
||||
// Six bits of TS_STATE are used.
|
||||
#define NO 0x00 // option is deactivated
|
||||
#define YES 0x01 // option is activated
|
||||
#define WANT_NO 0x02 // option is activated, negotiating to switch off
|
||||
#define WANT_YES 0x03 // option is deactivated, negotiating to switch on
|
||||
#define Q_EMPTY 0x00 // no entry in queue
|
||||
#define Q_OPPOSITE 0x04 // request to toggle state in queue
|
||||
#define REJECTED 0x08 // option denied, don't retry
|
||||
|
||||
// State and queue on the remote side (DO + DONT) (bits 0-3)
|
||||
#define Q_REMOTE(x) ((x) & 0x03)
|
||||
#define S_REMOTE(x, y) (((x) & ~0x03) | (y))
|
||||
#define Q_REMOTEQ(x) ((x) & 0x04)
|
||||
#define S_REMOTEQ(x, y) (((x) & ~0x04) | (y))
|
||||
#define Q_REMOTER(x) ((x) & 0x08)
|
||||
#define S_REMOTER(x, y) (((x) & ~0x08) | (y))
|
||||
// State and queue on this side (WILL + WONT) (bits 4-7)
|
||||
#define Q_LOCAL(x) (((x) & 0x30) >> 4)
|
||||
#define S_LOCAL(x,y) (((x) & ~0x30) | ((y) << 4))
|
||||
#define Q_LOCALQ(x) (((x) & 0x40) >> 4)
|
||||
#define S_LOCALQ(x, y) (((x) & ~0x40) | ((y) << 4))
|
||||
#define Q_LOCALR(x) (((x) & 0x80) >> 4)
|
||||
#define S_LOCALR(x, y) (((x) & ~0x80) | ((y) << 4))
|
||||
|
||||
// Access to mapping ts
|
||||
#define TS_STATE 0 // option state (yes, no, want yes, want no, Q)
|
||||
#define TS_SB 1 // sb infos (option specific)
|
||||
#define TS_R_AGREE 2 // preference or decision callback (remote state)
|
||||
#define TS_L_AGREE 3 // preference or decision callback (local state)
|
||||
#define TS_CB 4 // option state change callback (yes, no)
|
||||
#define TS_SBCB 5 // option sb callback
|
||||
#define TS_SIZE 6
|
||||
|
||||
// To have everything in one place we have one special key in ts
|
||||
#define TS_EXTRA -1 // key
|
||||
#define TSE_STATE 0 // input_to's INPUT_NOECHO and/or INPUT_CHARMODE
|
||||
#define TSE_TELNETNEG 1 // client answered a negotiation
|
||||
#define TSE_LOG 2 // negotiation log
|
||||
|
||||
// Bits used for the charmode and noecho state of the connection
|
||||
// Bits 0 + 1 used for TSE_NOECHO (set for noecho mode)
|
||||
// Bits 2 + 3 used for TSE_SGA_CHAR (set for charmode using SGA)
|
||||
// Bits 4 + 5 used for TSE_LM_CHAR (set for charmode using LINEMODE)
|
||||
// each representing the state with NO, YES, WANT_NO and WANT_YES
|
||||
#define Q_TSE_NOECHO ((ts[TS_EXTRA, TSE_STATE]) & 0x03)
|
||||
#define S_TSE_NOECHO(y) (ts[TS_EXTRA, TSE_STATE] = \
|
||||
((ts[TS_EXTRA, TSE_STATE]) & ~0x03) | (y))
|
||||
#define Q_TSE_SGA_CHAR (((ts[TS_EXTRA, TSE_STATE]) & 0x0c) >> 2)
|
||||
#define S_TSE_SGA_CHAR(y) (ts[TS_EXTRA, TSE_STATE] = \
|
||||
((ts[TS_EXTRA, TSE_STATE]) & ~0x0c) | ((y) << 2))
|
||||
#define Q_TSE_LM_CHAR (((ts[TS_EXTRA, TSE_STATE]) & 0x30) >> 4)
|
||||
#define S_TSE_LM_CHAR(y) (ts[TS_EXTRA, TSE_STATE] = \
|
||||
((ts[TS_EXTRA, TSE_STATE]) & ~0x30) | ((y) << 4))
|
||||
|
||||
#ifdef NEED_PRIVATE_PROTOTYPES
|
||||
#ifndef __TELNET_H_P_PROTO__
|
||||
#define __TELNET_H_P_PROTO__
|
||||
private int send(int* x);
|
||||
private void tel_error(string err);
|
||||
private void start_telnetneg();
|
||||
private string telnet_to_text(int command, int option, int* args);
|
||||
private void sb_ttype(int command, int option, int* optargs);
|
||||
private void sb_xdisp(int command, int option, int* optargs);
|
||||
private void sb_tspeed(int command, int option, int* optargs);
|
||||
private void sb_env(int command, int option, int* optargs);
|
||||
private void sb_naws(int command, int option, int* optargs);
|
||||
private void sb_status(int command, int option, int* optargs);
|
||||
private void sb_line(int command, int option, int* optargs);
|
||||
private int neg_sga(int command, int option);
|
||||
private int neg_echo(int command, int option);
|
||||
private int neg_bin(int command, int option);
|
||||
private int neg_tm(int command, int option);
|
||||
private void start_sb(int command, int option);
|
||||
private void start_eor(int command, int option);
|
||||
private void start_lm(int command, int option);
|
||||
private void cb_echo(int command, int option);
|
||||
private void cb_sga(int command, int option);
|
||||
static void modify_prompt(); // std/player/prompt.c
|
||||
#endif
|
||||
#endif // NEED_PRIVATE_PROTOTYPES
|
||||
|
||||
|
||||
// ************ Definitions for the TELNET protocol *************
|
||||
#define IAC 255 /* interpret as command: */
|
||||
#define DONT 254 /* you are not to use option */
|
||||
#define DO 253 /* please, you use option */
|
||||
#define WONT 252 /* I won't use option */
|
||||
#define WILL 251 /* I will use option */
|
||||
#define SB 250 /* interpret as subnegotiation */
|
||||
#define SE 240 /* end sub negotiation */
|
||||
#define EOR 239 /* end of record (transparent mode) */
|
||||
|
||||
#define TELCMDS ({\
|
||||
"EOR", "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",\
|
||||
"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC",\
|
||||
})
|
||||
/* backward starting with IAC == 255 */
|
||||
#define TELCMD2STRING(x) (((256-x)<sizeof(TELCMDS))?TELCMDS[<(256-x)]:(""+x))
|
||||
|
||||
/* telnet options */
|
||||
#define TELOPT_BINARY 0 /* 8-bit data path */
|
||||
#define TELOPT_ECHO 1 /* echo */
|
||||
#define TELOPT_RCP 2 /* prepare to reconnect */
|
||||
#define TELOPT_SGA 3 /* suppress go ahead */
|
||||
#define TELOPT_NAMS 4 /* approximate message size */
|
||||
#define TELOPT_STATUS 5 /* give status */
|
||||
#define TELOPT_TM 6 /* timing mark */
|
||||
#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
|
||||
#define TELOPT_NAOL 8 /* negotiate about output line width */
|
||||
#define TELOPT_NAOP 9 /* negotiate about output page size */
|
||||
#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
|
||||
#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
|
||||
#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
|
||||
#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
|
||||
#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
|
||||
#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
|
||||
#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
|
||||
#define TELOPT_XASCII 17 /* extended ascic character set */
|
||||
#define TELOPT_LOGOUT 18 /* force logout */
|
||||
#define TELOPT_BM 19 /* byte macro */
|
||||
#define TELOPT_DET 20 /* data entry terminal */
|
||||
#define TELOPT_SUPDUP 21 /* supdup protocol */
|
||||
#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
|
||||
#define TELOPT_SNDLOC 23 /* send location */
|
||||
#define TELOPT_TTYPE 24 /* terminal type */
|
||||
#define TELOPT_EOR 25 /* end or record */
|
||||
#define TELOPT_TUID 26 /* TACACS user identification */
|
||||
#define TELOPT_OUTMRK 27 /* output marking */
|
||||
#define TELOPT_TTYLOC 28 /* terminal location number */
|
||||
#define TELOPT_3270REGIME 29 /* 3270 regime */
|
||||
#define TELOPT_X3PAD 30 /* X.3 PAD */
|
||||
#define TELOPT_NAWS 31 /* window size */
|
||||
#define TELOPT_TSPEED 32 /* terminal speed */
|
||||
#define TELOPT_LFLOW 33 /* remote flow control */
|
||||
#define TELOPT_LINEMODE 34 /* linemode negotiations */
|
||||
#define TELOPT_XDISPLOC 35 /* X Display Location */
|
||||
#define TELOPT_ENVIRON 36 /* Environment opt for Port ID */
|
||||
#define TELOPT_AUTHENTICATION 37/* authentication */
|
||||
#define TELOPT_ENCRYPT 38 /* authentication */
|
||||
#define TELOPT_NEWENV 39 /* Environment opt for Port ID */
|
||||
|
||||
/* Inofficial, mud specific telnet options */
|
||||
#define TELOPT_COMPRESS 85 /* Mud Compression Protocol, v.1 */
|
||||
#define TELOPT_COMPRESS2 86 /* Mud Compression Protocol, v.2 */
|
||||
#define TELOPT_MSP 90 /* Mud Sound Protocol */
|
||||
#define TELOPT_MXP 91 /* Mud Extension Protocol */
|
||||
|
||||
#define TELOPT_EXOPL 255 /* extended-options-list */
|
||||
|
||||
#define NTELOPTS (1+TELOPT_NEWENV)
|
||||
#define TELOPTS ({\
|
||||
"BINARY", "ECHO", "RCP", "SGA", "NAME",\
|
||||
"STATUS", "TM", "RCTE", "NAOL", "NAOP",\
|
||||
"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",\
|
||||
"NAOVTD", "NAOLFD", "XASCII", "LOGOUT", "BM",\
|
||||
"DET", "SUPDUP", "SUPDUP OUTPUT",\
|
||||
"SENDLOC", "TTYPE", "EOR", \
|
||||
"TACACS UID", "OUTPUT MARKING", "TTYLOC",\
|
||||
"3270 REGIME", "X.3 PAD", "NAWS","TSPEED","LFLOW","LINEMODE",\
|
||||
"XDISPLOC","ENVIRON","AUTHENTICATION","ENCRYPT","NEWENV",\
|
||||
"TELOPT 40", "TELOPT 41", "TELOPT 42", "TELOPT 43",\
|
||||
"TELOPT 44", "TELOPT 45", "TELOPT 46", "TELOPT 47",\
|
||||
"TELOPT 48", "TELOPT 49", "TELOPT 50", "TELOPT 51",\
|
||||
"TELOPT 52", "TELOPT 53", "TELOPT 54", "TELOPT 55",\
|
||||
"TELOPT 56", "TELOPT 57", "TELOPT 58", "TELOPT 59",\
|
||||
"TELOPT 60", "TELOPT 61", "TELOPT 62", "TELOPT 63",\
|
||||
"TELOPT 64", "TELOPT 65", "TELOPT 66", "TELOPT 67",\
|
||||
"TELOPT 68", "TELOPT 69", "TELOPT 70", "TELOPT 71",\
|
||||
"TELOPT 72", "TELOPT 73", "TELOPT 74", "TELOPT 75",\
|
||||
"TELOPT 76", "TELOPT 77", "TELOPT 78", "TELOPT 79",\
|
||||
"TELOPT 80", "TELOPT 81", "TELOPT 82", "TELOPT 83",\
|
||||
"TELOPT 84", "MCCP1", "MCCP2", "TELOPT 87",\
|
||||
"TELOPT 88", "TELOPT 89", "MSP", "MEP",\
|
||||
})
|
||||
|
||||
#define TELOPT2STRING(x) ((x<sizeof(TELOPTS))?TELOPTS[x]:(""+x))
|
||||
|
||||
/* sub-option qualifiers */
|
||||
#define TELQUAL_IS 0 /* option is... */
|
||||
#define TELQUAL_SEND 1 /* send option */
|
||||
#define TELQUAL_INFO 2
|
||||
|
||||
#define TELQUAL2STRING(x) (x<3?({"IS","SEND","INFO"})[x]:""+x)
|
||||
|
||||
/*
|
||||
* LINEMODE suboptions
|
||||
*/
|
||||
|
||||
#define LM_MODE 1
|
||||
#define LM_FORWARDMASK 2
|
||||
#define LM_SLC 3
|
||||
|
||||
#define MODE_EDIT 0x01
|
||||
#define MODE_TRAPSIG 0x02
|
||||
#define MODE_ACK 0x04
|
||||
#define MODE_SOFT_TAB 0x08
|
||||
#define MODE_LIT_ECHO 0x10
|
||||
|
||||
#define MODE_MASK (MODE_EDIT|MODE_TRAPSIG|MODE_ACK|MODE_SOFT_TAB|MODE_LIT_ECHO)
|
||||
|
||||
#define SLC_SYNCH 1
|
||||
#define SLC_BRK 2
|
||||
#define SLC_IP 3
|
||||
#define SLC_AO 4
|
||||
#define SLC_AYT 5
|
||||
#define SLC_EOR 6
|
||||
#define SLC_ABORT 7
|
||||
#define SLC_EOF 8
|
||||
#define SLC_SUSP 9
|
||||
#define SLC_EC 10
|
||||
#define SLC_EL 11
|
||||
#define SLC_EW 12
|
||||
#define SLC_RP 13
|
||||
#define SLC_LNEXT 14
|
||||
#define SLC_XON 15
|
||||
#define SLC_XOFF 16
|
||||
#define SLC_FORW1 17
|
||||
#define SLC_FORW2 18
|
||||
#define SLC_MCL 19
|
||||
#define SLC_MCR 20
|
||||
#define SLC_MCWL 21
|
||||
#define SLC_MCWR 22
|
||||
#define SLC_MCBOL 23
|
||||
#define SLC_MCEOL 24
|
||||
#define SLC_INSRT 25
|
||||
#define SLC_OVER 26
|
||||
#define SLC_ECR 27
|
||||
#define SLC_EWR 28
|
||||
#define SLC_EBOL 29
|
||||
#define SLC_EEOL 30
|
||||
|
||||
#define SLC_NAMES ({"0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
|
||||
"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
|
||||
"LNEXT", "XON", "XOFF", "FORW1", "FORW2", \
|
||||
"MCL", "MCR", "MCWL", "MCWR", "MCBOL", "MCEOL", \
|
||||
"INSRT", "OVER", "ECR", "EWR", "EBOL", "EEOL"})
|
||||
|
||||
#define SLC2STRING(x) ((x)<sizeof(SLC_NAMES)?SLC_NAMES[x]:sprintf("%02x",x))
|
||||
|
||||
#define SLC_NOSUPPORT 0
|
||||
#define SLC_CANTCHANGE 1
|
||||
#define SLC_VARIABLE 2
|
||||
#define SLC_DEFAULT 3
|
||||
#define SLC_ACK 0x80
|
||||
#define SLC_FLUSHIN 0x40
|
||||
#define SLC_FLUSHOUT 0x20
|
||||
#define SLC_LEVELBITS 0x03
|
||||
|
||||
#define SLC_FLAGNAME ({ "NOSUPPORT", "CANTCHANGE", "VARIABLE", "DEFAULT" })
|
||||
|
||||
#define ENV_VAR 0
|
||||
#define ENV_VALUE 1
|
||||
#define ENV_ESC 2
|
||||
#define ENV_USERVAR 3
|
||||
|
||||
#endif
|
315
mudlib/test_master.c
Normal file
315
mudlib/test_master.c
Normal file
|
@ -0,0 +1,315 @@
|
|||
/* Test Master.c
|
||||
*
|
||||
* Minimal master.c to provide a very rudimentary test of the gamedriver.
|
||||
* To perform the test, cd to the directory this file is in and give the
|
||||
* command
|
||||
* driver -N -e -m. -Mtest_master.c -s-1 -sv-1 4242
|
||||
* (this assumes that you called the gamedriver 'driver' and that it is
|
||||
* in your searchpath).
|
||||
* Once it's running, telnet to localhost, port 4242. You should be
|
||||
* connected to the driver now and be able to enter commands.
|
||||
* The command 'help' will list you the commands available.
|
||||
*
|
||||
* A second test consists of the simple command
|
||||
* driver --version
|
||||
* The driver shall just print the version and exit immediately.
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void inaugurate_master (int arg)
|
||||
|
||||
// Initialise the master object.
|
||||
// We have to set the uid hooks, otherwise we can't clone a login object.
|
||||
|
||||
{
|
||||
set_driver_hook(2, unbound_lambda(({}), "uid"));
|
||||
set_driver_hook(3, unbound_lambda(({}), "uid"));
|
||||
set_driver_hook(10, "What?\n");
|
||||
#ifdef NOECHO
|
||||
set_driver_hook(13, "telnetneg");
|
||||
set_driver_hook(14, "set_noecho");
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int old_flag;
|
||||
|
||||
void set_noecho(int flag)
|
||||
{
|
||||
if (flag & ~old_flag & 1)
|
||||
{
|
||||
write("sending IAC WILL ECHO\n");
|
||||
binary_message(({ 0xff, 0xfb, 0x01 })); // IAC WILL ECHO
|
||||
}
|
||||
else if (old_flag & ~flag & 1)
|
||||
{
|
||||
write("sending IAC WONT ECHO\n");
|
||||
binary_message(({ 0xff, 0xfc, 0x01 })); // IAC WONT ECHO
|
||||
}
|
||||
if (flag & ~old_flag & 2)
|
||||
{
|
||||
write("sending IAC WILL+DO SGA\n");
|
||||
binary_message(({ 0xff, 0xfb, 0x03 })); // IAC WILL SGA
|
||||
binary_message(({ 0xff, 0xfd, 0x03 })); // IAC DO SGA
|
||||
}
|
||||
else if (old_flag & ~flag & 2)
|
||||
{
|
||||
write("sending IAC WONT+DONT SGA\n");
|
||||
binary_message(({ 0xff, 0xfc, 0x03 })); // IAC WONT SGA
|
||||
binary_message(({ 0xff, 0xfe, 0x03 })); // IAC DONT SGA
|
||||
}
|
||||
old_flag = flag;
|
||||
} /* set_noecho() */
|
||||
|
||||
void telnetneg(int a, int b, int* c)
|
||||
{
|
||||
// just ignore, should work with linux telnet
|
||||
printf("got %d %d %O\n", a,b,c);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
string get_simul_efun ()
|
||||
|
||||
// Load the simul-efun object "/sefun" if existing and return its pathname.
|
||||
|
||||
{
|
||||
object sefun;
|
||||
|
||||
if (!catch(sefun = load_object("/sefun")))
|
||||
return object_name(sefun);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
string get_master_uid()
|
||||
|
||||
// Return the master uid.
|
||||
{
|
||||
return " R O O T ";
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void flag (string arg)
|
||||
|
||||
// Evaluate an argument given as option '-f' to the driver.
|
||||
|
||||
{
|
||||
debug_message(sprintf("%O: flag(%O)\n", this_object(), arg));
|
||||
if (arg == "test")
|
||||
{
|
||||
/* Insert your test code here */
|
||||
return;
|
||||
}
|
||||
|
||||
if (arg == "gc")
|
||||
{
|
||||
garbage_collection();
|
||||
return;
|
||||
}
|
||||
|
||||
if (arg == "dhry")
|
||||
{
|
||||
limited( (: load_object("dhrystone")->main(1000) :) );
|
||||
shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
if (arg == "dhry2")
|
||||
{
|
||||
limited( (: load_object("dhrystone2")->main(1000) :) );
|
||||
shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
if (arg == "shutdown")
|
||||
{
|
||||
shutdown();
|
||||
return;
|
||||
}
|
||||
write ("master: Unknown flag "+arg+"\n");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
mixed prepare_destruct (object obj)
|
||||
|
||||
// Prepare the destruction of the object.
|
||||
|
||||
{
|
||||
debug_message(sprintf("%O: prepare_destruct(%O)\n", this_object(), obj));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
object connect ()
|
||||
|
||||
// Handle the request for a new connection.
|
||||
// We simply return a clone of ourself (we can't simply return this object
|
||||
// unfortunately), the gamedriver will then call logon() here.
|
||||
|
||||
{
|
||||
object obj;
|
||||
debug_message(sprintf("%O: connect()\n", this_object()));
|
||||
obj = clone_object(object_name(this_object()));
|
||||
return obj;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
static nomask mixed logon ()
|
||||
|
||||
// A connection was successfully bound to this object.
|
||||
// Print some status data and add the commands.
|
||||
|
||||
{
|
||||
debug_message(sprintf("%O: logon()\n", this_object()));
|
||||
write("\nLDMud " __VERSION__ "\n\n----------\n");
|
||||
write(debug_info(4,0));
|
||||
write("----------\n\n");
|
||||
enable_commands();
|
||||
add_action("f_help", "help");
|
||||
add_action("f_shutdown", "shutdown");
|
||||
add_action("f_echo", "echo");
|
||||
add_action("f_flag", "flag");
|
||||
add_action("f_gc", "gc");
|
||||
add_action("f_upd", "upd");
|
||||
add_action("f_quit", "quit");
|
||||
add_action("f_charmode", "charmode");
|
||||
set_combine_charset("abc");
|
||||
|
||||
return 1; // To verify that the connection was accepted.
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int f_help (string arg)
|
||||
|
||||
// The 'help' command.
|
||||
|
||||
{
|
||||
debug_message(sprintf("%O: f_help()\n", this_object()));
|
||||
write(
|
||||
" help - Prints this message\n"
|
||||
" shutdown - shuts down the driver\n"
|
||||
" flag - passes the argument to the flag() function\n"
|
||||
" echo - tests the input_to() function\n"
|
||||
" gc - performes a garbage collection\n"
|
||||
" upd - reloads the master object\n"
|
||||
" quit - terminates the connection, but leaves the driver running\n"
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int f_flag (string arg)
|
||||
|
||||
// The 'flag' command.
|
||||
|
||||
{
|
||||
debug_message(sprintf("%O: f_flag()\n", this_object()));
|
||||
flag(arg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int f_gc (string arg)
|
||||
|
||||
// The 'gc' command.
|
||||
|
||||
{
|
||||
write("Requested a garbage collection.\n");
|
||||
garbage_collection();
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int f_echo (string arg)
|
||||
|
||||
// The 'echo' command.
|
||||
|
||||
{
|
||||
debug_message(sprintf("%O: f_echo()\n", this_object()));
|
||||
input_to("echoline", 4, "Please enter a line: ");
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void echoline (string text)
|
||||
|
||||
// The user entered some text. Echo it.
|
||||
|
||||
{
|
||||
debug_message(sprintf("%O: echoline()\n", this_object()));
|
||||
write("You entered: '"+text+"'\n");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int f_charmode (string arg)
|
||||
{
|
||||
write("Entering charmode. Enter 'enough' to stop.\n");
|
||||
input_to("charinput", 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
string in;
|
||||
|
||||
void charinput(string char)
|
||||
{
|
||||
string cmd;
|
||||
|
||||
printf(" Got %O (%s)\n", char
|
||||
, implode(map(to_array(char), #'to_string),","));
|
||||
|
||||
if (!in)
|
||||
in = char;
|
||||
else if (!strlen(char) || char[0] == 13)
|
||||
{
|
||||
cmd = in;
|
||||
in = char[1..];
|
||||
}
|
||||
else
|
||||
{
|
||||
in += char;
|
||||
}
|
||||
if (cmd !="enough")
|
||||
input_to("charinput", 2);
|
||||
else
|
||||
write("Ok.\n");
|
||||
} /* charinput() */
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int f_shutdown (string arg)
|
||||
|
||||
// The 'shutdown' command.
|
||||
|
||||
{
|
||||
debug_message(sprintf("%O: f_shutdown()\n", this_object()));
|
||||
write("Shutting down.\n");
|
||||
shutdown();
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int f_upd (string arg)
|
||||
|
||||
// The 'upd' command.
|
||||
|
||||
{
|
||||
debug_message(sprintf("%O: f_upd()\n", this_object()));
|
||||
write("Removing old master...\n");
|
||||
destruct(find_object(__MASTER_OBJECT__));
|
||||
write("Loading master again...\n");
|
||||
load_object(__MASTER_OBJECT__);
|
||||
write("...done.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int f_quit (string arg)
|
||||
|
||||
// The 'quit' command.
|
||||
|
||||
{
|
||||
debug_message(sprintf("%O: f_quit()\n", this_object()));
|
||||
write("Bye-bye.\n");
|
||||
destruct(this_object());
|
||||
return 1;
|
||||
}
|
||||
|
14
mudlib/uni-crasher/README
Normal file
14
mudlib/uni-crasher/README
Normal file
|
@ -0,0 +1,14 @@
|
|||
This directory holds a LPC object which runs a stress test against the driver:
|
||||
it calls random efuns with random arguments and keeps a log of what has been
|
||||
called.
|
||||
|
||||
It was written for the Unitopia mudlib (and thusly uses some of their
|
||||
simul-efuns). To use it, copy secure.inc into the secure/simul_efun
|
||||
directory first.
|
||||
|
||||
crasher.c : the test object
|
||||
crashleak.c: a variant of the crasher object looking for memory leaks.
|
||||
secure.inc : a replacement for the original secure/simul_efun/secure.inc,
|
||||
so that the security-sensitive functions can be tested, too.
|
||||
|
||||
Written by Andreas "Menaures" Klauer.
|
831
mudlib/uni-crasher/crasher.c
Normal file
831
mudlib/uni-crasher/crasher.c
Normal file
|
@ -0,0 +1,831 @@
|
|||
/*
|
||||
crasher: Standardversion (Menaures 07.12.01)
|
||||
|
||||
ANLEITUNG:
|
||||
|
||||
1. Bei dem Define DEBUGGER den eigenen Real-Namen angeben
|
||||
|
||||
2. Define VERBOSE auskommentieren, falls nicht bereits so.
|
||||
VERBOSE kann genutzt werden, wenn gesicherte Dateien einen
|
||||
Crash ausloesen und die genaue Zeile gesucht wird.
|
||||
(VERBOSE gibt vor jedem einzelnen Aufruf momentane
|
||||
Datei und Zeile per debug_message aus).
|
||||
|
||||
3. Wenn bereits aufgenommene Dateien existieren, das EFuns und
|
||||
Values-Array NICHT modifizieren, bzw. nicht die Positionen
|
||||
der einzelnen Elemente aendern - sonst werden die aufgezeichneten
|
||||
Dateien unbrauchbar. Ebenso koennen nach solchen Modifikationen
|
||||
aufgenommene Dateien nicht mehr von alten Versionen des Crashers
|
||||
abgespielt werden.
|
||||
|
||||
Wer andere Values / Closures haben moechte, modifiziere die
|
||||
entsprechenden Arrays, speichere den Crasher unter einem anderen
|
||||
Filenamen und mache einen eindeutigen Eintrag im Header...
|
||||
|
||||
record:
|
||||
|
||||
record(file) speichert Ausfuehrungsablaeufe in Dateien namens
|
||||
file_xxxx, wobei xxxx eine Durchlaufnummer ist. Das Objekt
|
||||
braucht fuer diese Dateien logischerweise Schreibrecht.
|
||||
|
||||
Die aufgenommenen Dateien werden nach ihrer Erstellung automatisch
|
||||
ausgefuehrt. Fuehrt dies zu einem Crash, kann man das ganze einfach
|
||||
nochmals abspielen.
|
||||
|
||||
replay:
|
||||
|
||||
replay(file) spielt aufgenommene Dateien ab, fuehrt sie also aus.
|
||||
Dies ist dazu da, um Crashes, die dieses Objekt erzeugt, zu
|
||||
reproduzieren. Statt file wird file_xxxx eingelesen, wobei xxxx
|
||||
eine Durchlaufnummer ist.
|
||||
|
||||
execute_file:
|
||||
|
||||
Mit execute_file(file) kann man eine Datei gezielt ausfuehren.
|
||||
Dazu gibt man den echten Dateinamen der Datei an, inklusive
|
||||
Durchlaufnummer.
|
||||
|
||||
debug_query:
|
||||
|
||||
Mit debug_query(file, line) kann man abfragen, was in der Datei
|
||||
file in Zeile line ausgefuehrt werden wuerde - also welche
|
||||
Closure mit welchen Argumenten.
|
||||
|
||||
Hierzu muss der eigene Name als DEBUGGER definiert sein.
|
||||
|
||||
debug_exec:
|
||||
|
||||
Mit debug_exec(file, line) wird die angegebene Zeile in der
|
||||
Datei ausgefuehrt. Dadurch kann gezielt festgestellt werden,
|
||||
ob der einzelne Aufruf den Crash ausgeloest hat.
|
||||
|
||||
|
||||
Crash-Grund finden:
|
||||
|
||||
Bringt der Crasher den Driver zum Absturz, zunaechst den Driver
|
||||
neu starten und mit execute_file das zuletzt aufgenommene File
|
||||
abspielen.
|
||||
|
||||
Bringt das den Driver zum Crash, den gleichen Vorgang mit
|
||||
aktiviertem VERBOSE wiederholen, um die Zeilennummer herauszufinden.
|
||||
|
||||
Hat man erst einmal die Zeilennummer, laesst sich per debug_query
|
||||
herausfinden, was ausgefuehrt werden, und mit debug_exec pruefen,
|
||||
ob es wirklich der Ausloeser war.
|
||||
|
||||
Kann der Crash auf diese Weise nicht reproduziert werden, kann man
|
||||
einmal versuchen, alle aufgenommenen Dateien mit replay abzuspielen;
|
||||
fuehrt das zu keinem Crash, wurde der Crash nicht durch einen
|
||||
bestimmten Aufruf (oder eine bestimmte Folge selbiger) ausgeloest,
|
||||
sondern hat einen anderen Grund, der genauer untersucht werden muss.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define DEBUGGER "menaures"
|
||||
#include <debug.h>
|
||||
|
||||
// #define VERBOSE // Aktivieren, wenn man die crashausloesende Zeile sucht
|
||||
|
||||
#define MAX_ARGS 5
|
||||
#define DELAY 4
|
||||
#define ITERATIONS 1000
|
||||
|
||||
mixed execute;
|
||||
mixed efuns;
|
||||
mixed values;
|
||||
mixed names;
|
||||
|
||||
void record(string file);
|
||||
|
||||
void reset_all()
|
||||
{
|
||||
catch(
|
||||
|
||||
execute = 0,
|
||||
|
||||
( efuns =
|
||||
({
|
||||
#'Name,
|
||||
#'[,
|
||||
#'abs,
|
||||
#'abs_path,
|
||||
#'acos,
|
||||
#'add_action,
|
||||
#'add_dot_to_msg,
|
||||
// #'add_verb,
|
||||
// #'add_xverb,
|
||||
#'all_environment,
|
||||
#'all_inventory,
|
||||
#'allocate,
|
||||
// #'allocate_mapping,
|
||||
#'and_bits,
|
||||
#'apply,
|
||||
#'arr_delete,
|
||||
#'asin,
|
||||
// #'assoc,
|
||||
#'atan,
|
||||
#'atan2,
|
||||
#'attach_erq_demon,
|
||||
#'auto_owner_search,
|
||||
#'binary_message,
|
||||
#'bind_lambda,
|
||||
// #'break_point,
|
||||
#'call_other,
|
||||
#'call_out,
|
||||
#'call_out_info,
|
||||
#'call_resolved,
|
||||
#'caller_stack,
|
||||
#'caller_stack_depth,
|
||||
#'capitalize,
|
||||
#'cat,
|
||||
#'catch,
|
||||
#'ceil,
|
||||
#'center,
|
||||
#'clear_bit,
|
||||
#'clock,
|
||||
#'clone_object,
|
||||
#'clonep,
|
||||
// #'clones,
|
||||
#'closurep,
|
||||
#'command,
|
||||
#'command_stack,
|
||||
#'command_stack_depth,
|
||||
#'cond_present,
|
||||
#'convert_message,
|
||||
#'convert_umlaute,
|
||||
#'copies,
|
||||
#'copy,
|
||||
#'copy_bits,
|
||||
#'copy_file,
|
||||
// #'copy_mapping,
|
||||
#'cos,
|
||||
#'count_bits,
|
||||
#'crypt,
|
||||
#'ctime,
|
||||
// #'db_affected_rows,
|
||||
// #'db_close,
|
||||
// #'db_coldefs,
|
||||
// #'db_connect,
|
||||
// #'db_conv_string,
|
||||
// #'db_error,
|
||||
// #'db_exec,
|
||||
// #'db_fetch,
|
||||
// #'db_handles,
|
||||
// #'db_insert_id,
|
||||
#'debug_info,
|
||||
#'debug_message,
|
||||
#'deep_copy,
|
||||
#'deep_inventory,
|
||||
#'deep_present,
|
||||
#'dein,
|
||||
#'deinem,
|
||||
#'deinen,
|
||||
#'deines,
|
||||
#'dem,
|
||||
#'den,
|
||||
#'der,
|
||||
#'des,
|
||||
#'destruct,
|
||||
#'diesem,
|
||||
#'diesen,
|
||||
#'dieser,
|
||||
#'dieses,
|
||||
#'disable_commands,
|
||||
#'domain2map,
|
||||
#'ed,
|
||||
// #'efun308,
|
||||
#'ein,
|
||||
#'einem,
|
||||
#'einen,
|
||||
#'eines,
|
||||
#'enable_commands,
|
||||
#'environment,
|
||||
#'er,
|
||||
#'exec,
|
||||
#'execute_command,
|
||||
#'exp,
|
||||
#'expand_define,
|
||||
#'explode,
|
||||
#'export_uid,
|
||||
#'extern_call,
|
||||
// #'extract,
|
||||
// #'file_name,
|
||||
#'file_path,
|
||||
#'file_size,
|
||||
#'file_time,
|
||||
#'filter,
|
||||
// #'filter_array,
|
||||
#'filter_indices,
|
||||
// #'filter_mapping,
|
||||
#'filter_objects,
|
||||
#'find_call_out,
|
||||
#'find_living,
|
||||
#'find_object,
|
||||
#'find_player,
|
||||
#'first_inventory,
|
||||
#'floatp,
|
||||
#'floor,
|
||||
#'format_seconds,
|
||||
#'format_vseconds,
|
||||
#'funcall,
|
||||
#'function_exists,
|
||||
#'functionlist,
|
||||
#'garbage_collection,
|
||||
#'get_align_string,
|
||||
#'get_dir,
|
||||
#'get_error_file,
|
||||
#'get_eval_cost,
|
||||
#'get_extra_wizinfo,
|
||||
#'get_genitiv,
|
||||
#'get_type_info,
|
||||
#'get_unique_string,
|
||||
#'geteuid,
|
||||
#'getuid,
|
||||
#'gmtime,
|
||||
#'heart_beat_info,
|
||||
#'ihm,
|
||||
#'ihn,
|
||||
#'ihr,
|
||||
#'ihrem,
|
||||
#'ihren,
|
||||
#'ihres,
|
||||
#'implode,
|
||||
#'inherit_list,
|
||||
#'input_to,
|
||||
// #'insert_alist,
|
||||
#'interactive,
|
||||
// #'intersect_alist,
|
||||
#'intp,
|
||||
#'invert_bits,
|
||||
#'ist,
|
||||
#'lambda,
|
||||
#'last_bit,
|
||||
#'last_instructions,
|
||||
#'left,
|
||||
#'limited,
|
||||
#'liste,
|
||||
#'living,
|
||||
#'load_name,
|
||||
#'load_object,
|
||||
#'localtime,
|
||||
#'log,
|
||||
#'log_file,
|
||||
#'lower_case,
|
||||
#'m_allocate,
|
||||
#'m_contains,
|
||||
#'m_delete,
|
||||
#'m_indices,
|
||||
#'m_reallocate,
|
||||
// #'m_sizeof,
|
||||
#'m_values,
|
||||
#'make_shared_string,
|
||||
#'map,
|
||||
#'map2domain,
|
||||
// #'map_array,
|
||||
#'map_indices,
|
||||
// #'map_mapping,
|
||||
#'map_object,
|
||||
#'map_objects,
|
||||
// #'mapping_contains,
|
||||
#'mappingp,
|
||||
#'max,
|
||||
#'md5,
|
||||
#'member,
|
||||
// #'member_array,
|
||||
#'min,
|
||||
#'mixed2str,
|
||||
#'mixed_to_closure,
|
||||
#'mkdir,
|
||||
#'mkmapping,
|
||||
#'move_object,
|
||||
#'negate,
|
||||
#'next_bit,
|
||||
#'next_inventory,
|
||||
#'not_alone,
|
||||
#'notify_fail,
|
||||
#'object_info,
|
||||
#'object_name,
|
||||
#'object_time,
|
||||
#'objectp,
|
||||
#'or_bits,
|
||||
// #'order_alist,
|
||||
#'parse_com,
|
||||
#'parse_com_error,
|
||||
#'parse_com_error_string,
|
||||
#'player_exists,
|
||||
#'player_present,
|
||||
#'playerp,
|
||||
#'plural,
|
||||
#'pointerp,
|
||||
#'pol2xy,
|
||||
#'pow,
|
||||
#'present,
|
||||
#'present_clone,
|
||||
#'previous_object,
|
||||
#'printf,
|
||||
#'process_string,
|
||||
#'program_name,
|
||||
#'program_time,
|
||||
#'query_actions,
|
||||
// #'query_akkusativ,
|
||||
#'query_command,
|
||||
// #'query_dativ,
|
||||
#'query_deklin,
|
||||
#'query_deklin_adjektiv,
|
||||
#'query_deklin_ein_adjektiv,
|
||||
#'query_deklin_name,
|
||||
// #'query_dekliniert,
|
||||
#'query_editing,
|
||||
// #'query_genitiv,
|
||||
#'query_idle,
|
||||
// #'query_imp_port,
|
||||
#'query_input_pending,
|
||||
#'query_ip_name,
|
||||
#'query_ip_number,
|
||||
#'query_limits,
|
||||
#'query_living_name,
|
||||
#'query_livings,
|
||||
#'query_load_average,
|
||||
#'query_mud_port,
|
||||
#'query_notify_fail,
|
||||
#'query_once_interactive,
|
||||
#'query_pronom,
|
||||
#'query_real_player_level,
|
||||
#'query_shadowing,
|
||||
#'query_snoop,
|
||||
#'query_udp_port,
|
||||
#'query_up_time,
|
||||
#'query_verb,
|
||||
#'quote,
|
||||
#'raise_error,
|
||||
#'random,
|
||||
#'read_bytes,
|
||||
#'read_file,
|
||||
#'real_time_diff,
|
||||
#'referencep,
|
||||
#'regexp,
|
||||
#'regexplode,
|
||||
#'regreplace,
|
||||
#'remove_action,
|
||||
#'remove_call_out,
|
||||
#'remove_input_to,
|
||||
#'remove_interactive,
|
||||
#'rename,
|
||||
#'rename_object,
|
||||
#'replace_program,
|
||||
#'restore_object,
|
||||
#'restore_value,
|
||||
#'right,
|
||||
#'rm,
|
||||
#'rmdir,
|
||||
#'round,
|
||||
#'rusage,
|
||||
#'save_object,
|
||||
#'save_value,
|
||||
#'say,
|
||||
#'search_object,
|
||||
#'sein,
|
||||
#'seinem,
|
||||
#'seinen,
|
||||
#'seines,
|
||||
#'send_erq,
|
||||
// #'send_imp,
|
||||
#'send_udp,
|
||||
// #'set_auto_include_string,
|
||||
#'set_bit,
|
||||
#'set_buffer_size,
|
||||
#'set_combine_charset,
|
||||
#'set_connection_charset,
|
||||
#'set_driver_hook,
|
||||
#'set_environment,
|
||||
#'set_extra_wizinfo,
|
||||
#'set_extra_wizinfo_size,
|
||||
#'set_heart_beat,
|
||||
#'set_is_wizard,
|
||||
#'set_light,
|
||||
#'set_limits,
|
||||
#'set_living_name,
|
||||
#'set_modify_command,
|
||||
#'set_next_reset,
|
||||
#'set_prompt,
|
||||
#'set_this_object,
|
||||
#'set_this_player,
|
||||
#'seteuid,
|
||||
#'sgn,
|
||||
#'shadow,
|
||||
#'short_format_seconds,
|
||||
#'short_format_vseconds,
|
||||
#'shorttimestr,
|
||||
#'shortvtimestr,
|
||||
#'shout,
|
||||
#'shutdown,
|
||||
#'sin,
|
||||
#'sizeof,
|
||||
// #'slice_array,
|
||||
#'snoop,
|
||||
#'sort_array,
|
||||
#'space,
|
||||
#'sprintf,
|
||||
#'sqrt,
|
||||
#'sscanf,
|
||||
#'str2int,
|
||||
#'string_parser,
|
||||
#'stringp,
|
||||
#'strip,
|
||||
#'strlen,
|
||||
#'strstr,
|
||||
#'substr,
|
||||
// #'swap,
|
||||
#'symbol_function,
|
||||
#'symbol_variable,
|
||||
#'symbolp,
|
||||
#'sys_log,
|
||||
#'tail,
|
||||
#'tan,
|
||||
#'tell_object,
|
||||
#'tell_room,
|
||||
#'terminal_colour,
|
||||
#'test_bit,
|
||||
#'this_interactive,
|
||||
#'this_object,
|
||||
#'this_player,
|
||||
#'throw,
|
||||
#'time,
|
||||
#'time_to_vtime,
|
||||
#'timestr,
|
||||
#'to_array,
|
||||
#'to_float,
|
||||
#'to_int,
|
||||
#'to_object,
|
||||
#'to_string,
|
||||
#'touch,
|
||||
#'trace,
|
||||
#'traceprefix,
|
||||
#'transpose_array,
|
||||
#'trim,
|
||||
#'typeof,
|
||||
#'unbound_lambda,
|
||||
#'unique_array,
|
||||
#'unmkmapping,
|
||||
#'unshadow,
|
||||
#'upper_case,
|
||||
#'users,
|
||||
#'utime,
|
||||
#'vclock,
|
||||
#'vtime,
|
||||
#'vtime_to_time,
|
||||
#'vtimestr,
|
||||
#'walk_mapping,
|
||||
#'wem,
|
||||
#'wen,
|
||||
#'wer,
|
||||
#'wessen,
|
||||
#'widthof,
|
||||
#'wizardshellp,
|
||||
#'wizlist_info,
|
||||
#'wrap,
|
||||
#'wrap_say,
|
||||
#'write,
|
||||
#'write_bytes,
|
||||
#'write_file,
|
||||
#'xor_bits,
|
||||
#'xy2pol,
|
||||
|
||||
#',,
|
||||
#'=,
|
||||
#'+=,
|
||||
#'-=,
|
||||
#'&=,
|
||||
#'|=,
|
||||
#'^=,
|
||||
#'<<=,
|
||||
#'>>=,
|
||||
#'>>>=,
|
||||
#'*=,
|
||||
#'%=,
|
||||
#'/=,
|
||||
#'?,
|
||||
#'||,
|
||||
#'&&,
|
||||
#'|,
|
||||
#'^,
|
||||
#'&,
|
||||
#'==,
|
||||
#'!=,
|
||||
#'>,
|
||||
#'>=,
|
||||
#'<,
|
||||
#'<=,
|
||||
#'<<,
|
||||
#'>>,
|
||||
#'>>>,
|
||||
#'+,
|
||||
#'-,
|
||||
#'*,
|
||||
#'%,
|
||||
#'/,
|
||||
#'++,
|
||||
#'--,
|
||||
#'negate,
|
||||
#'!,
|
||||
#'~,
|
||||
#'({,
|
||||
#'([,
|
||||
#'[,
|
||||
#'[<,
|
||||
#'[..],
|
||||
#'[..<],
|
||||
#'[<..],
|
||||
#'[<..<],
|
||||
#'[..,
|
||||
#'[<..,
|
||||
#'({,
|
||||
#'([,
|
||||
}) ),
|
||||
|
||||
( values =
|
||||
({
|
||||
/* --- Integers: --- */
|
||||
0,
|
||||
1,
|
||||
-1,
|
||||
32,
|
||||
-32,
|
||||
40,
|
||||
-40,
|
||||
29292929,
|
||||
-5050211,
|
||||
__INT_MAX__,
|
||||
__INT_MIN__,
|
||||
|
||||
/* --- Floats: --- */
|
||||
0.0,
|
||||
0.5,
|
||||
-0.5,
|
||||
55.5,
|
||||
-55.5,
|
||||
999999999999999999999999999999999999999999999.99,
|
||||
-999999999999999999999999999999999999999999999.99,
|
||||
|
||||
/* --- Strings: --- */
|
||||
"",
|
||||
"foo bar",
|
||||
"%d %q %T",
|
||||
"0",
|
||||
"",
|
||||
" ",
|
||||
"_",
|
||||
"^^^^^^",
|
||||
"#^# #^#",
|
||||
" ^",
|
||||
"^ ",
|
||||
" - - - - ",
|
||||
"? ? ? ? ? ? ????? ???? ??",
|
||||
"°°°°°°°°°°°°°°°°°°°°°",
|
||||
"\\/ "*32,
|
||||
" !"*42,
|
||||
|
||||
/* --- Objekte: --- */
|
||||
touch("/obj/fackel"),
|
||||
touch("/obj/rucksack"),
|
||||
touch("/obj/rope"),
|
||||
touch("/secure/master"),
|
||||
clone_object("/obj/schiff"),
|
||||
clone_object("/obj/player"),
|
||||
clone_object("/obj/tisch"),
|
||||
|
||||
/* --- Closures: --- */
|
||||
(: :),
|
||||
(: (: 1 :) :),
|
||||
#'sizeof,
|
||||
#'garbage_collection,
|
||||
symbol_function("query_long", touch("/i/item")),
|
||||
lambda( ({'x, 'y}), ({#'?, ({#'>, 'x, 'y}), 'x, 'y}) ),
|
||||
unbound_lambda( ({'x}), ({#'==, 0, 'x}) ),
|
||||
|
||||
/* --- Arrays: --- */
|
||||
({ }),
|
||||
({ 0 }),
|
||||
({ "" }),
|
||||
({ ({ }) }),
|
||||
({ ([ ]) }),
|
||||
allocate(3000),
|
||||
|
||||
/* --- Mappings: --- */
|
||||
([ ]),
|
||||
([ (: :) ]),
|
||||
m_allocate(5,5),
|
||||
mkmapping(allocate(30), allocate(30, ({})), allocate(30, (:1:))),
|
||||
|
||||
}) )
|
||||
|
||||
); // catch
|
||||
|
||||
if(pointerp(values)) {
|
||||
values += ({0,0,0});
|
||||
|
||||
apply((: values[<3] = $1 :), &execute);
|
||||
apply((: values[<2] = $1 :), &values);
|
||||
apply((: values[<1] = $1 :), &efuns);
|
||||
}
|
||||
while(remove_call_out("execute_file") != -1);
|
||||
while(remove_call_out("do_replay") != -1);
|
||||
while(remove_call_out("do_record") != -1);
|
||||
|
||||
seteuid(getuid());
|
||||
}
|
||||
|
||||
int execute_file(string file)
|
||||
{
|
||||
int line;
|
||||
string str;
|
||||
mixed restore;
|
||||
|
||||
if(!stringp(file) || file_size(file) <= 0)
|
||||
{
|
||||
DEBUG("ERROR: Cannot execute "+file+": Invalid file.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG("Executing: "+file);
|
||||
|
||||
for(line = 0; (str=read_file(file, line, 2)) && strlen(str); line += 2)
|
||||
{
|
||||
restore = restore_value(str);
|
||||
|
||||
rm("/save/crash/LAST_EXEC");
|
||||
write_file("/save/crash/LAST_EXEC",
|
||||
save_value( ({file, line}) ));
|
||||
|
||||
#ifdef VERBOSE
|
||||
debug_message("File: "+file+" Line: "+line+"\n");
|
||||
#endif
|
||||
debug_message(sprintf("REPLAY: %O %O -> %O %O\n", restore[0], restore[1], efuns[ restore[0] ], map( restore[1], (: values[$1] :) )));
|
||||
|
||||
catch(
|
||||
apply( efuns[ restore[0] ],
|
||||
map( restore[1], (: values[$1] :) ) )
|
||||
);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
mixed query_values() { return values; }
|
||||
|
||||
int generate_file(string file)
|
||||
{
|
||||
int i, h, efun_index, * value_index;
|
||||
|
||||
if(!stringp(file) || !write_file(file, ""))
|
||||
{
|
||||
DEBUG("ERROR: Cannot write file: "+file);
|
||||
debug_message(wrap("ERROR: Cannot write file: "+file));
|
||||
|
||||
seteuid(getuid());
|
||||
|
||||
record("/save/crash/"+(mixed2str(utime())-"({,})"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG("Recording: "+file);
|
||||
|
||||
for(i = ITERATIONS; i--; )
|
||||
{
|
||||
efun_index = random(sizeof(efuns));
|
||||
value_index = ({});
|
||||
|
||||
for(h = random(MAX_ARGS+1); h--; )
|
||||
{
|
||||
value_index += ({ random(sizeof(values)) });
|
||||
}
|
||||
|
||||
write_file(file, save_value( ({efun_index, value_index}) ));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void replay(string file)
|
||||
{
|
||||
if (!file)
|
||||
{
|
||||
file = names[0];
|
||||
names = names[1..];
|
||||
}
|
||||
DEBUG("Stopping all actions and starting REPLAY for: "+file);
|
||||
|
||||
reset_all();
|
||||
|
||||
execute = ({ #'call_out, "do_replay", DELAY, file, 1 });
|
||||
|
||||
// Um this_player etc. loszuwerden einen Reset-Hack ;o)
|
||||
set_next_reset(DELAY);
|
||||
}
|
||||
|
||||
static void do_replay(string file, int number)
|
||||
{
|
||||
if(execute_file(file + right(number, 5, "_0000")))
|
||||
{
|
||||
call_out("do_replay", DELAY, file, number+1);
|
||||
}
|
||||
else call_out("replay", DELAY, 0);
|
||||
}
|
||||
|
||||
void record(string file)
|
||||
{
|
||||
DEBUG("Stopping all actions and starting RECORD for: "+file);
|
||||
|
||||
reset_all();
|
||||
|
||||
execute = ({ #'call_out, "do_record", DELAY, file, 1 });
|
||||
|
||||
// Um this_player etc. loszuwerden einen Reset-Hack ;o)
|
||||
set_next_reset(DELAY);
|
||||
}
|
||||
|
||||
static void do_record(string file, int number)
|
||||
{
|
||||
if(generate_file(file+right(number, 5, "_0000")))
|
||||
{
|
||||
call_out("execute_file", DELAY, file+right(number, 5, "_0000"));
|
||||
call_out("do_record", DELAY*2, file, number+1);
|
||||
}
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
// Um this_player etc. loszuwerden einen Reset-Hack ;o)
|
||||
if(execute)
|
||||
{
|
||||
apply(execute[0], execute[1..]);
|
||||
execute = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void debug_query(string file, int line)
|
||||
{
|
||||
mixed restore;
|
||||
|
||||
restore = restore_value(read_file(file, line, 2));
|
||||
|
||||
rm("/save/crash/TEMP");
|
||||
write_file("/save/crash/TEMP",
|
||||
sprintf("apply( %Q, %Q )", efuns[ restore[0] ],
|
||||
map(restore[1], (: values[$1] :))));
|
||||
|
||||
({this_player()})->more("/save/crash/TEMP");
|
||||
}
|
||||
|
||||
void debug_exec(string file, int line)
|
||||
{
|
||||
mixed restore;
|
||||
|
||||
restore = restore_value(read_file(file, line, 2));
|
||||
|
||||
catch(
|
||||
apply( efuns[ restore[0] ], map(restore[1], (: values[$1] :)))
|
||||
);
|
||||
}
|
||||
|
||||
void create()
|
||||
{
|
||||
string str;
|
||||
mixed strs;
|
||||
|
||||
reset_all();
|
||||
|
||||
str = read_file("/save/crash/LAST_EXEC");
|
||||
|
||||
if(str)
|
||||
{
|
||||
catch( apply( #'debug_query, restore_value(str) ),
|
||||
write_file("/save/crash/CRASHERS",
|
||||
"-"*80 + "\n"
|
||||
+ read_file("/save/crash/TEMP")+ "\n" ) );
|
||||
}
|
||||
|
||||
#if 0
|
||||
strs = get_dir("/save/crash/1*");
|
||||
|
||||
foreach(str : strs)
|
||||
{
|
||||
rm("/save/crash/"+str);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
call_out("record", 4, "/save/crash/"+(mixed2str(utime())-"({,})"));
|
||||
#else
|
||||
names = ({
|
||||
"/save/crash/crash1"
|
||||
});
|
||||
call_out("replay", 4, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* --- End of file. --- */
|
686
mudlib/uni-crasher/crashleak.c
Normal file
686
mudlib/uni-crasher/crashleak.c
Normal file
|
@ -0,0 +1,686 @@
|
|||
// This is for crash purposes only. Don't run it in a production MUD.
|
||||
//
|
||||
// It may still depend on some UNItopia stuff, I haven't tested it with other
|
||||
// libs. If you're using the UNItopia Mudlib to run it, you have to remove all
|
||||
// nomask simul efuns (empty the file /secure/simul_efun/secure.inc), and
|
||||
// unlock all privilege violations in /secure/master/compiler_control.inc by
|
||||
// adding return 1; of the function.
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
// File: crashleak.c
|
||||
// Description: Try to crash the driver and/or find memory leaks
|
||||
// by calling EFuns and Operators with random arguments.
|
||||
// Based on my old crasher.c
|
||||
// Author: Menaures@UNItopia (2004-07-17)
|
||||
//
|
||||
|
||||
/* --- Documentation: --- */
|
||||
|
||||
/* --- Inherits: --- */
|
||||
|
||||
/* --- Includes: --- */
|
||||
#include <rtlimits.h>
|
||||
|
||||
// Replace this with some kind of output if you
|
||||
// want Debug-Messages
|
||||
#define DEBUG(x) {}
|
||||
|
||||
/* --- Defines: --- */
|
||||
|
||||
// Undef the following if you're not interested in Memleaks
|
||||
#define FIND_MEMORY_LEAKS
|
||||
|
||||
// Where shall we write our data to?
|
||||
#define CRASHLEAK_DIR "/save/crashleak/"
|
||||
|
||||
// Where is the doc/efun directory of the driver package?
|
||||
#define DOC_EFUN_DIR CRASHLEAK_DIR"doc/efun/"
|
||||
|
||||
#define FILE(x,y) (CRASHLEAK_DIR+l_time+"_"+sprintf("%'0'6d_%s", (y), (x)))
|
||||
#define GC_FILE(x) FILE("GC_"+(x), ++filecounter)
|
||||
#define RECORD_FILE(x) FILE("REC_"+(x), ++filecounter)
|
||||
#define LEAK_FILE(x) FILE("LEAK_"+(x), ++filecounter)
|
||||
#define LOG_FILE(x) FILE("LOG_"+(x), ++filecounter)
|
||||
|
||||
// How many calls shall we do per step?
|
||||
#define CALLS_PER_STEP 1000
|
||||
|
||||
// How long to wait between steps?
|
||||
// Careful, Memleak detection might not work for lower values!
|
||||
#define STEP_PAUSE 4
|
||||
|
||||
// Sometimes objects get removed out of the values array.
|
||||
// Do you want to reinitialize it every X steps?
|
||||
// For maximum Memleak Find reliability, set to 1,
|
||||
// which causes reinitialization in every step (halfing
|
||||
// the speed)
|
||||
#define REINIT_EVERY_N_STEPS 10
|
||||
|
||||
// This defines minimum and maximum number of arguments per
|
||||
// function call. Recorded files may still be executed with
|
||||
// old values if you change this.
|
||||
#define MIN_PARAMS 0
|
||||
#define MAX_PARAMS 15
|
||||
|
||||
// NOTE:
|
||||
// When looking for Memleaks, only one step per PAUSE will be made.
|
||||
// Thus, detecting all Memleaks of one real step will require
|
||||
// a minimum of CALLS_PER_STEP*STEP_PAUSE time until the next step
|
||||
// is done with full stress speed again. This is probably a long
|
||||
// time, however: if there are few leaks, lower CALLS_PER_STEP
|
||||
// will only add up to the time it takes to find one in the first
|
||||
// place...
|
||||
|
||||
/* --- Global Variables: --- */
|
||||
|
||||
int l_time = time(); // Just as a unique number...
|
||||
mixed * efun; // EFun- and Operator-Closures. Either #'foo or ({#'foo, min_param, max_param})
|
||||
mixed * value; // Value-set which contains all Data Types.
|
||||
int stepcounter; // For reinit after N steps.
|
||||
int filecounter; // For file naming.
|
||||
mixed * queue; // Queue, to have one call-out-loop instead of many
|
||||
#ifdef FIND_MEMORY_LEAKS
|
||||
mixed * leakage; // To track GCs and Execs for Leak detection.
|
||||
#endif
|
||||
|
||||
/* --- Prototypes: --- */
|
||||
|
||||
void crash(string file, closure callback);
|
||||
void leak(closure callback);
|
||||
|
||||
#ifdef FIND_MEMORY_LEAKS
|
||||
void check_for_leak(string file, mixed * exec);
|
||||
void step_by_step(string gc_file, string file, mixed * exec);
|
||||
#endif
|
||||
|
||||
/* --- Functions: --- */
|
||||
|
||||
/* --- Queue --- */
|
||||
|
||||
// Basic Queue, mainly to prevent recursion problems.
|
||||
// And to make call_out loops easier (we have more than one)
|
||||
|
||||
mixed * query_queue() { return queue; }
|
||||
|
||||
int push(int pos, varargs mixed * what)
|
||||
{
|
||||
if(!pointerp(queue))
|
||||
{
|
||||
queue = ({});
|
||||
}
|
||||
|
||||
if(pos <= 0)
|
||||
{
|
||||
pos = sizeof(queue) + 1;
|
||||
}
|
||||
|
||||
queue = queue[0..pos-2] + ({ what }) + queue[pos-1..];
|
||||
}
|
||||
|
||||
int pop()
|
||||
{
|
||||
mixed q;
|
||||
|
||||
if(pointerp(queue) && sizeof(queue))
|
||||
{
|
||||
q = queue[0];
|
||||
queue = queue[1..];
|
||||
apply(q[0],q[1..]);
|
||||
return sizeof(queue);
|
||||
}
|
||||
}
|
||||
|
||||
void step()
|
||||
{
|
||||
if(set_next_reset(0) > 300)
|
||||
{
|
||||
set_next_reset(150);
|
||||
}
|
||||
|
||||
pop();
|
||||
call_out(#'step, STEP_PAUSE);
|
||||
}
|
||||
|
||||
/* --- Crashleak Initialization: --- */
|
||||
|
||||
// Just to provide some LFun Closures below...
|
||||
string foo() { return "foo"; }
|
||||
mixed bar(mixed x, mixed y, mixed z) { return ({z,y,x}); }
|
||||
|
||||
mixed query_efun() { return efun; }
|
||||
|
||||
void init_efun()
|
||||
{
|
||||
DEBUG("init_efun()");
|
||||
// Generate list of all EFuns. /doc/efun/ is part of the driver package.
|
||||
// If it isn't part of your mudlib directory, copy it somewhere in it
|
||||
// and modify the path accordingly.
|
||||
string * list = get_dir(DOC_EFUN_DIR"*") - ({".","..","[]"});
|
||||
|
||||
// Convert them to EFun closures using a restore_value hack.
|
||||
|
||||
efun = restore_value("#1:0\n({#e:"+implode(list, ",#e:")+",})\n");
|
||||
|
||||
// Kill unrecognized and dangerous EFuns.
|
||||
efun -= ({0,
|
||||
#'efun::set_driver_hook, // it makes the crasher stop running
|
||||
#'efun::limited, // too much fun
|
||||
#'efun::set_this_object, // poses problems
|
||||
#'efun::garbage_collection, // Can't find no leaks otherwise
|
||||
#'efun::shutdown, // Can't find no crashes otherwise
|
||||
#'efun::set_limits}); // Messes things up naturally
|
||||
|
||||
// Add Operator closures. Have not found a way to generate this list
|
||||
// automatically yet, so you might want to check if it's still up2date.
|
||||
// See lex.c ~ approx line 1000 for a list (this one's of 2004/07/17).
|
||||
efun +=
|
||||
({ #'+= ,#'++ ,#'+ ,#'-= ,#'-- ,#'- ,#'*= ,#'* ,#'/=
|
||||
,#'/ ,#'%= ,#'% ,#', ,#'^= ,#'^ ,#'|| ,#'||= ,#'|=
|
||||
,#'| ,#'&& ,#'&&= ,#'&= ,#'& ,#'~ ,#'<= ,#'<<= ,#'<<
|
||||
,#'< ,#'>= ,#'>>= ,#'>>>= ,#'>>> ,#'>> ,#'> ,#'== ,#'=
|
||||
,#'!= ,#'! ,#'?! ,#'? ,#'[..] ,#'[..<] ,#'[<..]
|
||||
,#'[<..<] ,#'[..>] ,#'[>..] ,#'[<..>]
|
||||
,#'[>..<] ,#'[>..>] ,#'[.. ,#'[<..
|
||||
,#'[>.. ,#'[,] ,#'[ ,#'[< ,#'[>
|
||||
,#'({ ,#'([ ,#'-> ,#'(<
|
||||
});
|
||||
}
|
||||
|
||||
mixed query_values() { return value; }
|
||||
|
||||
struct Bar {
|
||||
mixed four;
|
||||
};
|
||||
|
||||
struct Foo {
|
||||
int one, *two;
|
||||
struct Bar three;
|
||||
};
|
||||
|
||||
void init_value()
|
||||
{
|
||||
DEBUG("init_value()");
|
||||
|
||||
// The more values, the more variation, the better.
|
||||
// Feel free to add stuff to this list. However, don't modify it
|
||||
// on the fly, changing this array will make recorded files useless.
|
||||
|
||||
// Please refrain from using self-referencing structures unless you
|
||||
// want to test the crash aspect only. Include self-referencing
|
||||
// stuff inside #ifndef FIND_MEMORY_LEAKS #endif blocks only.
|
||||
|
||||
if(pointerp(value))
|
||||
{
|
||||
// Do some cleanup first:
|
||||
map(value, (: objectp($1) && destruct($1) :));
|
||||
}
|
||||
|
||||
value = 0;
|
||||
value =
|
||||
({
|
||||
/* --- Integer: --- */
|
||||
-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,
|
||||
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
|
||||
-1000,1000,-50000,50000,-2000000,2000000,
|
||||
__INT_MIN__+16,__INT_MAX__-16,__INT_MIN__,__INT_MAX__,
|
||||
|
||||
/* --- Float: --- */
|
||||
0.0,0.001,-0.001,-0.5,0.5,0.99,-0.99,1.01,-1.01,
|
||||
42.767,-42.767,1.0,2.0,3.0,-1.0,-2.0,-3.0,
|
||||
to_float(__INT_MIN__), to_float(__INT_MAX__),
|
||||
1.0e+100, -1.0e+100,
|
||||
|
||||
/* --- String: --- */
|
||||
"", " ", " ", "!_!_", "_!_!",
|
||||
"foo","bar","foo bar", "%d", "%Q", "0", "^^^^^^",
|
||||
"#^# #^#", " ^",
|
||||
"^ ", " - - - - ",
|
||||
"? ? ? ? ? ? ????? ???? ??", "",
|
||||
"\\/ "*32, " !"*42, "/", "/..",
|
||||
"/a", "/d/", "/w/..",
|
||||
"%#Q%#Q%#Q","%d%-=80s%%",
|
||||
save_value(efun), save_object(),
|
||||
|
||||
/* --- Object: --- */
|
||||
|
||||
// This is mudlib specific, please provide some objects;
|
||||
// Preferred are Blueprints, Clones, Objects with Environment,
|
||||
// and Objects which have other objects inside (rooms).
|
||||
//
|
||||
// Note that random calls (for example to destruct()) might
|
||||
// remove objects; so they should be reloaded here.
|
||||
// A proper cleanup of old objects then would probably be good too.
|
||||
load_object("/obj/fackel"), clone_object("/obj/fackel"),
|
||||
load_object("/obj/player"), clone_object("/obj/player"),
|
||||
load_object("/i/item/message"),
|
||||
clone_object("/obj/rucksack"), clone_object("/obj/kurstafel"),
|
||||
clone_object("/obj/wizard_shell"), clone_object("/secure/obj/login"),
|
||||
load_object("/secure/obj/login"), load_object("/apps/error_db"),
|
||||
load_object("/apps/plugin"), clone_object("/obj/zauberstab"),
|
||||
load_object("/room/church"), load_object("/room/void"),
|
||||
load_object("/room/hell"), load_object("/room/death/death"),
|
||||
load_object("/room/rathaus/treppe"),
|
||||
load_object("/room/rathaus/konferenz"),
|
||||
load_object("/room/rathaus/forum"),
|
||||
clone_object("/obj/monster"), clone_object("/obj/monster"),
|
||||
clone_object("/obj/monster"), clone_object("/obj/monster"),
|
||||
|
||||
/* --- Closure: --- */
|
||||
(: :), (: 1 :), (: 0 :), (: $2/$1 :),
|
||||
#'efun::max, #'efun::input_to, #'efun::this_player,
|
||||
#'efun::this_object, #'efun::call_out,
|
||||
symbol_function("query_long", load_object("/i/item")),
|
||||
symbol_function("query_real_name", load_object("/i/player/player")),
|
||||
#'foo, #'bar,
|
||||
function { return 2 * $1; },
|
||||
function int (int a) { return 2 * a; },
|
||||
function (int a) { return 2 * a; },
|
||||
lambda( ({'x, 'y}), ({#'?, ({#'>, 'x, 'y}), 'x, 'y}) ),
|
||||
unbound_lambda( ({'x}), ({#'==, 0, 'x}) ),
|
||||
(: for(;;); :), (: while($1); :),
|
||||
|
||||
/* --- Array: --- */
|
||||
({}), ({ ({}) }), ({ (: :) }), ({ 0 }), ({ 1 }),
|
||||
({ "" }), ({ ([]) }), ({#'efun::min}),
|
||||
allocate(5), allocate(10,1), allocate(query_limits(1)[LIMIT_ARRAY]),
|
||||
({'x, 'y}), ({#'?, ({#'>, 'x, 'y}), 'x, 'y}),
|
||||
({'x}), ({#'==, 0, 'x}),
|
||||
|
||||
/* --- Mapping: --- */
|
||||
([:0]), ([:1]), ([:2]), (["a":"b"]),([([1]):({2,3})]),
|
||||
mkmapping( ({1,2,3,4,5,6,7,8,9,10}), ({1,2,3,4,5,6,7,8,9,10}) ),
|
||||
mkmapping( ({"1","2","3","4","5","6","7","8","9","10"}) ),
|
||||
([ load_object("/apps/groups") ]),
|
||||
([ #'efun::allocate ]),
|
||||
|
||||
/* --- Symbol / Quoted: --- */
|
||||
'a, 'b, 'c, quote(allocate(10)),
|
||||
'dont_know_what_this_is_supposed_to_be_it_sure_is_fun,
|
||||
'whatever_floats_your_boat,
|
||||
|
||||
/* --- Struct: --- */
|
||||
});
|
||||
|
||||
// --- Lets add some special values. ---
|
||||
|
||||
// Container inside Container inside...
|
||||
object ob = clone_object("/obj/rucksack");
|
||||
|
||||
|
||||
for(int i = 10; i--; )
|
||||
{
|
||||
object ob2 = clone_object("/obj/rucksack");
|
||||
ob->move(ob2);
|
||||
ob=ob2;
|
||||
}
|
||||
|
||||
value += ({ob});
|
||||
|
||||
// Some random strings. Good for crashing, bad for debugging...
|
||||
// So to make things reproducible, we generate them only once,
|
||||
// and only load them afterwards. Delete the Savefile if you
|
||||
// want new random strings.
|
||||
|
||||
string str;
|
||||
|
||||
if(str = read_file(CRASHLEAK_DIR"random_strings.o"))
|
||||
{
|
||||
value += restore_value(str);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
string * random_strings = ({});
|
||||
|
||||
for(int i = 10; i--; )
|
||||
{
|
||||
int * arr;
|
||||
|
||||
arr = map(allocate(random(100)), (: random(256) :));
|
||||
random_strings += ({ to_string(arr) });
|
||||
}
|
||||
|
||||
// Save these strings so that we can reuse them next time.
|
||||
write_file(CRASHLEAK_DIR"random_strings.o",
|
||||
save_value(random_strings));
|
||||
|
||||
// Don't forget to add them to the values array...
|
||||
value += random_strings;
|
||||
}
|
||||
|
||||
// Structs
|
||||
struct Bar foo = (<Bar> 10);
|
||||
struct Foo bar = (<Foo> 1, ({"2",3}), (<Bar> 5));
|
||||
|
||||
value += ({foo,bar})*20;
|
||||
}
|
||||
|
||||
mixed do_plot_efun(closure cl)
|
||||
{
|
||||
// DEBUG(sprintf("do_plot_efun(%#Q)",cl));
|
||||
|
||||
object ob = this_object();
|
||||
|
||||
int min_p = MIN_PARAMS;
|
||||
int max_p = MAX_PARAMS;
|
||||
|
||||
for(int p = MAX_PARAMS; p >= MIN_PARAMS; p--)
|
||||
{
|
||||
|
||||
|
||||
string str = catch(apply(cl, allocate(p)); nolog);
|
||||
|
||||
// DEBUG(sprintf(" str -> %#Q", str));
|
||||
|
||||
if(str && strstr(str, "many arguments") != -1)
|
||||
{
|
||||
max_p--;
|
||||
}
|
||||
|
||||
else if(str && strstr(str, "few arguments") != -1)
|
||||
{
|
||||
min_p++;
|
||||
}
|
||||
}
|
||||
|
||||
set_this_object(ob);
|
||||
seteuid(0);
|
||||
seteuid(getuid());
|
||||
|
||||
if(min_p != MIN_PARAMS || max_p != MAX_PARAMS)
|
||||
{
|
||||
return ({cl, min_p, max_p});
|
||||
}
|
||||
|
||||
return cl;
|
||||
}
|
||||
|
||||
void plot_efun()
|
||||
{
|
||||
DEBUG("plot_efun()");
|
||||
|
||||
efun = filter(efun, #'closurep);
|
||||
efun = limited(#'map, ({10000000}), efun, #'do_plot_efun);
|
||||
|
||||
garbage_collection(GC_FILE("plot_efun"));
|
||||
}
|
||||
|
||||
void init_crashleak(closure callback)
|
||||
{
|
||||
DEBUG("init_crashleak()");
|
||||
|
||||
// Sometimes init fails. Recall.
|
||||
push(1, #'init_crashleak, callback);
|
||||
|
||||
string str;
|
||||
|
||||
if(str = catch(limited(#'init_efun, ({1000000})); publish))
|
||||
{
|
||||
debug_message("CRASHLEAK: init_efun failed:\n"+str+"\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(str = catch(limited(#'init_value, ({1000000})); publish))
|
||||
{
|
||||
debug_message("CRASHLEAK: init_value failed:\n"+str+"\n");
|
||||
}
|
||||
|
||||
garbage_collection(GC_FILE("AFTER_INIT"));
|
||||
|
||||
// Del the old entry
|
||||
queue = queue[1..];
|
||||
push(0, callback);
|
||||
|
||||
// Determine EFun parameter counts next step.
|
||||
push(1, #'plot_efun);
|
||||
}
|
||||
|
||||
void crashleak()
|
||||
{
|
||||
DEBUG("crashleak()");
|
||||
|
||||
if(stepcounter++ == REINIT_EVERY_N_STEPS)
|
||||
{
|
||||
init_crashleak(#'crashleak);
|
||||
stepcounter=0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#ifdef FIND_MEMORY_LEAKS
|
||||
push(0, #'crash, RECORD_FILE("cl"), #'check_for_leak);
|
||||
#else
|
||||
push(0, #'crash, RECORD_FILE("cl"), #'crashleak);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* --- Crash Execution: --- */
|
||||
|
||||
mixed * pick()
|
||||
{
|
||||
DEBUG("pick()");
|
||||
|
||||
mixed * erg = ({});
|
||||
|
||||
int f, p;
|
||||
|
||||
for(int i = CALLS_PER_STEP; i--; )
|
||||
{
|
||||
f = random(sizeof(efun));
|
||||
|
||||
if(closurep(efun[f]))
|
||||
{
|
||||
p = MIN_PARAMS + random(MAX_PARAMS-MIN_PARAMS);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
p = efun[f][1] + random(efun[f][2]-efun[f][1]);
|
||||
}
|
||||
|
||||
|
||||
erg +=
|
||||
({
|
||||
// Pick EFun index.
|
||||
({ random(sizeof(efun)),
|
||||
// Pick p parameter indices.
|
||||
map(allocate(p), (: random(sizeof(value)) :)),
|
||||
// Will be replaced with a string later:
|
||||
// (debugmessage of what was executed)
|
||||
0
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
return erg;
|
||||
}
|
||||
|
||||
varargs void exec(mixed * exec, int quiet)
|
||||
{
|
||||
DEBUG("exec()");
|
||||
|
||||
string file;
|
||||
string text = "";
|
||||
object ob = this_object();
|
||||
|
||||
debug_message("start_of_exec\n");
|
||||
|
||||
foreach(mixed * x : exec)
|
||||
{
|
||||
mixed f = efun[x[0]];
|
||||
if(pointerp(f)) f=f[0];
|
||||
mixed * v = map(x[1], (: value[$1] :));
|
||||
string str = sprintf("%d %#Q\n", x[0],x[1]);
|
||||
|
||||
// Note: This chance affects arrays by reference. :-)
|
||||
x[2] = str;
|
||||
|
||||
debug_message(sprintf("exec: %s",str));
|
||||
|
||||
set_this_object(ob);
|
||||
seteuid(0);
|
||||
seteuid(getuid());
|
||||
catch(apply(f, v); reserve (max(get_eval_cost()/2,100000)), nolog);
|
||||
|
||||
if(get_eval_cost() < 100000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
set_this_object(ob);
|
||||
|
||||
debug_message("end_of_exec\n");;
|
||||
}
|
||||
|
||||
void crash(string file, closure callback)
|
||||
{
|
||||
DEBUG("crash()");
|
||||
|
||||
mixed * exec;
|
||||
|
||||
/* --- Pick what we will execute in this run: --- */
|
||||
exec = limited(#'pick, ({1000000}));
|
||||
|
||||
/* --- Record it to the file. --- */
|
||||
write_file(file, save_value(exec));
|
||||
|
||||
/* --- Execute it. --- */
|
||||
limited(#'exec, ({1000000}), exec);
|
||||
|
||||
funcall(callback, file, exec);
|
||||
}
|
||||
|
||||
/* --- Leak detection: --- */
|
||||
|
||||
int analyze(string gc_file)
|
||||
{
|
||||
DEBUG("analyze("+gc_file+")");
|
||||
|
||||
string s = read_file(gc_file);
|
||||
|
||||
if(!stringp(s))
|
||||
{
|
||||
debug_message(sprintf("CRASHLEAK: Could not read file %#Q (%#Q)!\n",gc_file,s));
|
||||
return 0;
|
||||
}
|
||||
|
||||
string * str = explode(s, "\n");
|
||||
|
||||
return sizeof(regexp(str, "freeing.*block"));
|
||||
}
|
||||
|
||||
void leak_gc(string file, mixed * exec)
|
||||
{
|
||||
DEBUG("leak_gc( ["+sizeof(exec)+"] )");
|
||||
|
||||
string sbs = GC_FILE("sbs");
|
||||
|
||||
// GC.
|
||||
garbage_collection(sbs);
|
||||
// Note this file will be created later.
|
||||
|
||||
// Push.
|
||||
push(1, #'step_by_step, sbs, file, exec);
|
||||
|
||||
// Execute.
|
||||
limited(#'exec, ({1000000}), exec, 1);
|
||||
}
|
||||
|
||||
void step_by_step(string gc_file, string file, mixed * exec)
|
||||
{
|
||||
DEBUG("step_by_step()");
|
||||
|
||||
// Okay. Binary search.
|
||||
|
||||
// Was there a leak?
|
||||
if(analyze(gc_file))
|
||||
{
|
||||
// Whee! There was one. Let's see what we do.
|
||||
|
||||
// How many execs are there which might have caused the leak?
|
||||
if(sizeof(exec) == 1)
|
||||
{
|
||||
// Only one? Okay, this is it then.
|
||||
DEBUG("LEAK: "+exec[0][2]+"\n");
|
||||
write_file(LEAK_FILE(explode(gc_file,"/")[<1]), exec[0][2]+"\n");
|
||||
|
||||
// We haven't done a GC, so we can pop:
|
||||
call_out(#'pop, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Okay. Do the first half now...
|
||||
leak_gc(file, exec[..(sizeof(exec)/2)-1]);
|
||||
// ...push the second half into the first queue, coz we can't do
|
||||
// to garbage_collection() at once.
|
||||
push(1, #'leak_gc, file, exec[(sizeof(exec)/2)..]);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// We haven't done a GC, so we can pop:
|
||||
call_out(#'pop, 0);
|
||||
}
|
||||
|
||||
// And wait...
|
||||
}
|
||||
|
||||
void check_for_leak(string file, mixed * exec)
|
||||
{
|
||||
DEBUG("check_for_leak()");
|
||||
|
||||
string gc_file = GC_FILE("check_for_leak");
|
||||
|
||||
// Warning: This is actually executed at the end of the cycle,
|
||||
// and not right now.
|
||||
garbage_collection(gc_file);
|
||||
// This means gc_file does not exist now yet.
|
||||
|
||||
// Check previous leakage (their gc_file exists now)
|
||||
if(leakage && analyze(leakage[0]))
|
||||
{
|
||||
// We need to do a step by step further investigation
|
||||
// of this exec to find which call exactly has caused
|
||||
// the leak.
|
||||
push(0, #'step_by_step, leakage[0], leakage[1], leakage[2]);
|
||||
|
||||
// Continue Crashing afterwards.
|
||||
push(0, #'crashleak);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// nothing to do. continue crashing.
|
||||
crashleak();
|
||||
}
|
||||
|
||||
// Remember this leakage and test it in the next run.
|
||||
leakage = ({gc_file,file,exec});
|
||||
}
|
||||
|
||||
/* --- Applied LFuns: --- */
|
||||
|
||||
void reset()
|
||||
{
|
||||
if(sizeof(queue) <= 0)
|
||||
{
|
||||
push(0, #'init_crashleak, #'crashleak);
|
||||
}
|
||||
|
||||
if(find_call_out(#'step) <= 0)
|
||||
{
|
||||
call_out(#'step, STEP_PAUSE);
|
||||
}
|
||||
}
|
||||
|
||||
void create()
|
||||
{
|
||||
DEBUG("create()");
|
||||
|
||||
garbage_collection(GC_FILE("AFTER_CREATE"));
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
/* --- End of file. --- */
|
152
mudlib/uni-crasher/secure.inc
Normal file
152
mudlib/uni-crasher/secure.inc
Normal file
|
@ -0,0 +1,152 @@
|
|||
// This file is part of UNItopia Mudlib.
|
||||
// ----------------------------------------------------------------
|
||||
// File: /secure/simul_efun/secure.inc
|
||||
// Description: Security Funktionen / Gesperrte Funktionen
|
||||
// Author: Freaky
|
||||
// Modified by: Freaky (31.03.1999) set_environment, object_info hinzugefuegt
|
||||
// Freaky (26.06.1999) command hinzugefuegt
|
||||
//
|
||||
// $Log: secure.inc,v $
|
||||
// Revision 1.1.1.1 2006/07/10 02:42:07 lynx
|
||||
// ldmud 3.3.714
|
||||
//
|
||||
// Revision 1.3 2001/01/30 23:59:01 sissi
|
||||
// Bergeweise CVS Log Eintraege eingetragen.
|
||||
// Hoffentlich nirgends doppelt und nirgends zu wenig.
|
||||
//
|
||||
|
||||
#pragma strict_types
|
||||
#pragma save_types
|
||||
|
||||
//
|
||||
// Dieser File ist der einizge Teil der Simul Efun mit
|
||||
// nomask simul_efun Privileg.
|
||||
// (siehe /secure/master/compiler_control::privilege_violation())
|
||||
//
|
||||
|
||||
/*
|
||||
* Nur der Shutdown-Daemon darf die efun shutdown verwenden!
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Gesperrte efuns
|
||||
*/
|
||||
#if __EFUN_DEFINED__(shutdown)
|
||||
nomask void shutdown() {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
#if __EFUN_DEFINED__(set_next_reset)
|
||||
nomask int set_next_reset(int delay) {}
|
||||
#endif
|
||||
*/
|
||||
|
||||
#if __EFUN_DEFINED__(heart_beat_info)
|
||||
nomask object *heart_beat_info() {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(object_info)
|
||||
nomask mixed *object_info(object ob, int what) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(debug_info)
|
||||
nomask varargs mixed debug_info(int flag, mixed m) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(move_object)
|
||||
nomask void move_object(object ob1, object ob2) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(set_this_player)
|
||||
nomask void set_this_player(object ob) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(set_environment)
|
||||
nomask void set_environment(object ob1, object ob2) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(efun308)
|
||||
nomask void efun308(object ob1, object ob2) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(swap)
|
||||
nomask void swap(object ob) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(break_point)
|
||||
nomask void break_point() {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(functionlist)
|
||||
nomask mixed *functionlist(mixed ob, int flag) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(query_actions)
|
||||
nomask mixed *query_actions(mixed ob, mixed flag) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(garbage_collection)
|
||||
nomask void garbage_collection() {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(command)
|
||||
nomask int command(string str) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(last_instructions)
|
||||
nomask varargs string *last_instructions(int len, int verbose) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(command_stack)
|
||||
nomask mixed *command_stack() {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(command_stack_depth)
|
||||
nomask int command_stack_depth() {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(set_buffer_size)
|
||||
nomask int set_buffer_size(int size) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
#if __EFUN_DEFINED__(restore_value)
|
||||
nomask mixed restore_value(string str) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(save_value)
|
||||
nomask string save_value(mixed m) {}
|
||||
#endif
|
||||
*/
|
||||
|
||||
/*
|
||||
#if __EFUN_DEFINED__(clones)
|
||||
nomask varargs object *clones(mixed m, int i) {}
|
||||
#endif
|
||||
*/
|
||||
|
||||
#if __EFUN_DEFINED__(set_connection_charset)
|
||||
nomask void set_connection_charset(mixed a, int i) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(binary_message)
|
||||
nomask varargs int binary_message(mixed m, int i) {}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(query_ip_number)
|
||||
nomask varargs string query_ip_number(object who)
|
||||
{
|
||||
return "0.0.0.0";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __EFUN_DEFINED__(query_ip_name)
|
||||
nomask varargs string query_ip_name(object who)
|
||||
{
|
||||
return "leider.nicht.mehr.verfuegbar";
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
332
psyclpc.1
Normal file
332
psyclpc.1
Normal file
|
@ -0,0 +1,332 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36.
|
||||
.TH PSYCLPC "1" "April 2007" "psyclpc 4.0.0 - a multi-protocol network server application language." "User Commands"
|
||||
.SH NAME
|
||||
psyclpc \- psyclpc
|
||||
.SH SYNOPSIS
|
||||
.B psyclpc
|
||||
[\fIoptions\fR] [\fI<portnumber>\fR...]
|
||||
.SH DESCRIPTION
|
||||
psyclpc 4.0.0 \- a multi\-protocol network server application language.
|
||||
.PP
|
||||
Release: Build 1.5 (mostly stable); 2007\-04\-17
|
||||
Compiled: Apr 17 2007 15:39:05
|
||||
.PP
|
||||
Options are:
|
||||
.HP
|
||||
\fB\-\-args\fR <filename>
|
||||
.IP
|
||||
Read the options from <filename> as if they were given on the
|
||||
commandline.
|
||||
.HP
|
||||
\fB\-P\fR|\-\-inherit <fd\-number>
|
||||
.IP
|
||||
Inherit filedescriptor <fd\-number> from the parent process
|
||||
as socket to listen for connections.
|
||||
.HP
|
||||
\fB\-u\fR|\-\-udp <portnumber>
|
||||
.IP
|
||||
Specify the <portnumber> for the UDP port, overriding the compiled\-in
|
||||
default.
|
||||
.HP
|
||||
\fB\-D\fR|\-\-define <macro>[=<text>]
|
||||
.IP
|
||||
Add <macro> (optionally to be expanded to <text>) to the list of
|
||||
predefined macros known by the LPC compiler.
|
||||
.HP
|
||||
\fB\-E\fR|\-\-eval\-cost <ticks>
|
||||
.IP
|
||||
Set the number of <ticks> available for one evaluation thread.
|
||||
.HP
|
||||
\fB\-M\fR|\-\-master <filename>
|
||||
.IP
|
||||
Use <filename> for the master object.
|
||||
.HP
|
||||
\fB\-m\fR|\-\-mudlib <pathname>
|
||||
.IP
|
||||
Use <pathname> as the top directory of the mudlib.
|
||||
.HP
|
||||
\fB\-\-debug\-file\fR <filename>
|
||||
.IP
|
||||
Log all debug output in <filename> instead of <host>.debug.log .
|
||||
.HP
|
||||
\fB\-\-hostname\fR <name>
|
||||
.IP
|
||||
Use <name> as hostname, instead of what the system says.
|
||||
.HP
|
||||
\fB\-\-hostaddr\fR <addr>
|
||||
.IP
|
||||
Use <addr> as address of this machine, instead of what the
|
||||
system says. In particular this address will be used to open
|
||||
the driver ports.
|
||||
.HP
|
||||
\fB\-\-compat\fR
|
||||
.HP
|
||||
\fB\-\-no\-compat\fR
|
||||
.IP
|
||||
Select the mode (compat or plain) of the driver.
|
||||
Note that this choice does not affect the default name of the master
|
||||
object.
|
||||
.HP
|
||||
\fB\-d\fR|\-\-debug
|
||||
.IP
|
||||
Generate debug output; repeat the argument for even more output.
|
||||
.HP
|
||||
\fB\-c\fR|\-\-list\-compiles
|
||||
.IP
|
||||
List the name of every compiled file on stderr.
|
||||
.HP
|
||||
\fB\-e\fR|\-\-no\-preload
|
||||
.IP
|
||||
Pass a non\-zero argument (the number of occurences of this option)
|
||||
to master\->preload(), which usually inhibits all preloads of castles
|
||||
and other objects.
|
||||
.HP
|
||||
\fB\-\-erq\fR <filename>
|
||||
.HP
|
||||
\fB\-\-erq\fR "<filename> <erq arguments>"
|
||||
.IP
|
||||
Use <filename> instead of 'erq' as the name of the ERQ executable.
|
||||
If the name starts with a '/', it is take to be an absolute pathname,
|
||||
otherwise it is interpreted relative to /opt/psyced/bin.
|
||||
If not specified, 'erq' is used as executable name.
|
||||
With the proper use of quotes it is legal to pass arbitrary arguments
|
||||
to the erq, however, these may not contain spaces themselves.
|
||||
.HP
|
||||
\fB\-N\fR|\-\-no\-erq
|
||||
.IP
|
||||
Don't start the erq demon (if it would be started at all).
|
||||
.HP
|
||||
\fB\-\-alarm\-time\fR <time>
|
||||
.IP
|
||||
The granularity of call_out()s and heartbeats (minimum: 1).
|
||||
.HP
|
||||
\fB\-\-heart\-interval\fR <time>
|
||||
.IP
|
||||
The time to elapse between two heartbeats (minimum: 1).
|
||||
.HP
|
||||
\fB\-\-sync\-heart\fR
|
||||
.IP
|
||||
All heartbeats are executed at the same time (modulo granularity).
|
||||
.HP
|
||||
\fB\-\-async\-heart\fR
|
||||
.IP
|
||||
Heartbeats are executed immediately when they are due (modulo granularity).
|
||||
.HP
|
||||
\fB\-t\fR|\-\-no\-heart
|
||||
.IP
|
||||
Disable heartbeats and call_outs.
|
||||
.HP
|
||||
\fB\-f\fR|\-\-funcall <word>
|
||||
.IP
|
||||
The lfun master\->flag() is called with <word> as argument before the
|
||||
gamedriver accepts network connections.
|
||||
.HP
|
||||
\fB\-\-cleanup\-time\fR <time>
|
||||
.IP
|
||||
The idle time in seconds for an object before the driver tries to
|
||||
clean it up. This time should be substantially higher than the
|
||||
reset time. A time <= 0 disables the cleanup mechanism.
|
||||
.HP
|
||||
\fB\-\-reset\-time\fR <time>
|
||||
.IP
|
||||
The time in seconds for an object before it is reset.
|
||||
A time <= 0 disables the reset mechanism.
|
||||
.HP
|
||||
\fB\-\-regexp\fR pcre|traditional
|
||||
.IP
|
||||
Select the default regexp package.
|
||||
.HP
|
||||
\fB\-\-max\-array\fR <size>
|
||||
.IP
|
||||
The maximum number of elements an array can hold.
|
||||
Set to 0, arrays of any size are allowed.
|
||||
.HP
|
||||
\fB\-\-max\-callouts\fR <number>
|
||||
.IP
|
||||
The maximum number of callouts at one time.
|
||||
Set to 0, any number of callouts is allowed.
|
||||
.HP
|
||||
\fB\-\-max\-mapping\fR <size>
|
||||
.IP
|
||||
The maximum number of elements (keys+values) a mapping can hold.
|
||||
Set to 0, mappings of any size are allowed.
|
||||
.HP
|
||||
\fB\-\-max\-mapping\-keys\fR <size>
|
||||
.IP
|
||||
The maximum number of entries (keys) a mapping can hold.
|
||||
Set to 0, mappings of any size are allowed.
|
||||
.HP
|
||||
\fB\-\-max\-bytes\fR <size>
|
||||
.IP
|
||||
The maximum number of bytes one read_bytes()/write_bytes() call
|
||||
can handle.
|
||||
Set to 0, reads and writes of any size are allowed.
|
||||
.HP
|
||||
\fB\-\-max\-file\fR <size>
|
||||
.IP
|
||||
The maximum number of bytes one read_file()/write_file() call
|
||||
can handle.
|
||||
Set to 0, reads and writes of any size are allowed.
|
||||
.HP
|
||||
\fB\-\-max\-thread\-pending\fR <size>
|
||||
.IP
|
||||
The maximum number of bytes to be kept pending by the socket write
|
||||
thread.
|
||||
Set to 0, an unlimited amount of data can be kept pending.
|
||||
(Ignored since pthreads are not supported)
|
||||
.TP
|
||||
\fB\-s\fR <time>
|
||||
| \fB\-\-swap\-time\fR <time>
|
||||
.HP
|
||||
\fB\-s\fR v<time> | \fB\-\-swap\-variables\fR <time>
|
||||
.IP
|
||||
Time in seconds before an object (or its variables) are swapped out.
|
||||
A time less or equal 0 disables swapping.
|
||||
.HP
|
||||
\fB\-s\fR f<name> | \fB\-\-swap\-file\fR <name>
|
||||
.IP
|
||||
Swap into file <name> instead of log/ldmud.swap.<host> .
|
||||
.HP
|
||||
\fB\-s\fR c | \fB\-\-swap\-compact\fR
|
||||
.IP
|
||||
Reuse free space in the swap file immediately.
|
||||
.HP
|
||||
\fB\-\-max\-malloc\fR <size>
|
||||
.IP
|
||||
Restrict total memory allocations to <size> bytes. A <size> of 0
|
||||
or 'unlimited' removes any restriction.
|
||||
.HP
|
||||
\fB\-\-min\-malloc\fR <size>
|
||||
.HP
|
||||
\fB\-\-min\-small\-malloc\fR <size>
|
||||
.IP
|
||||
Determine the sizes for the explicite initial large resp. small chunk
|
||||
allocation. A size of 0 disables the explicite initial allocations.
|
||||
.HP
|
||||
\fB\-r\fR u<size> | \fB\-\-reserve\-user\fR <size>
|
||||
.HP
|
||||
\fB\-r\fR m<size> | \fB\-\-reserve\-master\fR <size>
|
||||
.HP
|
||||
\fB\-r\fR s<size> | \fB\-\-reserve\-system\fR <size>
|
||||
.IP
|
||||
Reserve <size> amount of memory for user/master/system allocations to
|
||||
be held until main memory runs out.
|
||||
.HP
|
||||
\fB\-\-filename\-spaces\fR
|
||||
.HP
|
||||
\fB\-\-no\-filename\-spaces\fR
|
||||
.IP
|
||||
Allow/disallow the use of spaces in filenames.
|
||||
.HP
|
||||
\fB\-\-strict\-euids\fR
|
||||
.HP
|
||||
\fB\-\-no\-strict\-euids\fR
|
||||
.IP
|
||||
Enforce/don't enforce the proper use of euids.
|
||||
.HP
|
||||
\fB\-\-share\-variables\fR
|
||||
.HP
|
||||
\fB\-\-init\-variables\fR
|
||||
.IP
|
||||
Select how clones initialize their variables:
|
||||
.IP
|
||||
\- by sharing the current values of their blueprint
|
||||
\- by initializing them afresh (using __INIT()).
|
||||
.HP
|
||||
\fB\-\-tls\-key\fR <pathname>
|
||||
.IP
|
||||
Use <pathname> as the x509 keyfile, default is 'key.pem'.
|
||||
If relative, <pathname> is interpreted relative to <mudlib>.
|
||||
.HP
|
||||
\fB\-\-tls\-cert\fR <pathname>
|
||||
.IP
|
||||
Use <pathname> as the x509 certfile, default is 'cert.pem'.
|
||||
If relative, <pathname> is interpreted relative to <mudlib>.
|
||||
.IP
|
||||
Use <pathname> as the filename holding your trusted PEM certificates.
|
||||
If relative, <pathname> is interpreted relative to <mudlib>.
|
||||
.IP
|
||||
Use <pathname> as the directory where your trusted PEM certificates reside,
|
||||
default is '/etc/ssl/certs'.
|
||||
If relative, <pathname> is interpreted relative to <mudlib>.
|
||||
.IP
|
||||
Use <pathname> as the filename holding your certificate revocation lists.
|
||||
If relative, <pathname> is interpreted relative to <mudlib>.
|
||||
.IP
|
||||
Use <pathname> as the directory where your certificate revocation lists reside.
|
||||
If relative, <pathname> is interpreted relative to <mudlib>.
|
||||
.HP
|
||||
\fB\-\-wizlist\-file\fR <filename>
|
||||
.HP
|
||||
\fB\-\-no\-wizlist\-file\fR
|
||||
.IP
|
||||
Read and save the wizlist in the named file (always interpreted
|
||||
relative the mudlib); resp. don't read or save the wizlist.
|
||||
.HP
|
||||
\fB\-\-pidfile\fR <filename>
|
||||
.IP
|
||||
Write the pid of the driver process into <filename>.
|
||||
.HP
|
||||
\fB\-\-random\-seed\fR <num>
|
||||
.IP
|
||||
Seed value for the random number generator. If not given, the
|
||||
driver chooses a seed value on its own.
|
||||
.HP
|
||||
\fB\-\-gcollect\-outfd\fR <filename>|<num>
|
||||
.IP
|
||||
Garbage collector output (like a log of all reclaimed memory blocks)
|
||||
is sent to <filename> (or inherited fd <num>) instead of stderr.
|
||||
.HP
|
||||
\fB\-\-check\-refcounts\fR
|
||||
.IP
|
||||
Every backend cycle, all refcounts in the system are checked.
|
||||
SLOW!
|
||||
.HP
|
||||
\fB\-\-check\-state\fR <lvl>
|
||||
.IP
|
||||
Perform a regular simplistic check of the virtual machine according
|
||||
to <lvl>:
|
||||
.IP
|
||||
= 0: no check
|
||||
= 1: once per backend loop
|
||||
= 2: at various points in the backend loop
|
||||
.HP
|
||||
\fB\-\-gobble\-descriptors\fR <num>
|
||||
.IP
|
||||
<num> (more) filedescriptors are used up. You'll know when you need it.
|
||||
.HP
|
||||
\fB\-\-options\fR
|
||||
.IP
|
||||
Print the version and compilation options of the driver, then exit.
|
||||
.HP
|
||||
\fB\-V\fR|\-\-version
|
||||
.IP
|
||||
Print the version of the driver, then exit.
|
||||
.HP
|
||||
\fB\-\-longhelp\fR
|
||||
.IP
|
||||
Display this help and exit.
|
||||
.HP
|
||||
\fB\-h\fR|\-?|\-\-help
|
||||
.IP
|
||||
Display the short help text and exit.
|
||||
.PP
|
||||
Release: Build 1.5 (mostly stable); 2007\-04\-17
|
||||
Compiled: Apr 17 2007 15:39:05
|
||||
.SH CONTACT
|
||||
psyclpc is being maintained by fippo & lynX.
|
||||
|
||||
fippo is available at psyc://goodadvice.pages.de/~fippo
|
||||
or xmpp:fippo@goodadvice.pages.de
|
||||
|
||||
lynX is available as psyc://psyced.org/~lynx
|
||||
|
||||
You can reach us at psyc://psyced.org/@welcome
|
||||
.SH HISTORY
|
||||
psyclpc, an LDMud with a couple of patches and optimization for psyced,
|
||||
available from <http://lpc.psyc.eu>.
|
||||
|
||||
LDMud itself is a continuation of the Amylaar LPMud Gamedriver 3.1.2.
|
||||
See also <http://www.bearnip.com/lars/proj/ldmud.html>.
|
||||
|
||||
psyclpc is released under the GNU LIBRARY GENERAL PUBLIC LICENSE, Version 2.
|
81
src/C_COMPILER_BUGS
Normal file
81
src/C_COMPILER_BUGS
Normal file
|
@ -0,0 +1,81 @@
|
|||
gcc version 2.9-aix51-020209:
|
||||
make_func.y::read_func_spec() a too large fprintf() statement
|
||||
causes the compiler to generated faulty code on the assignment which
|
||||
causes the mkfunc program to crash. Splitting the print statement
|
||||
into two solved the problem.
|
||||
|
||||
Visual Age C 6.0, AIX 5.2:
|
||||
make_func.y::read_func_spec() the particularly sized fprintf() statement
|
||||
causes the compiler to generated faulty code on the following assignment,
|
||||
which in turn causes the mkfunc program to generate faulty data. Splitting
|
||||
the print statement into two solved the problem.
|
||||
|
||||
gcc 2.9, 3.2 - Cygwin
|
||||
Highest optimization creates buggy code when the total size of local
|
||||
variables gets too big (>= 8KBytes).
|
||||
|
||||
gcc 3.0
|
||||
Optimization option -funroll-all-loops seems to create buggy code.
|
||||
|
||||
gcc 2.91.66 19990314/Linux (egcs-1.1.2) on Linux/x86:
|
||||
Computing MIN_LONG % -1 causes a floating point exception.
|
||||
|
||||
xlc on AIX 3.4:
|
||||
Optimization level -O4 -qipa crashes in the code generation if a void
|
||||
returning function is casted to a value returning one.
|
||||
|
||||
egcs 2.91.66 on Linux 2.2.15 on Sun SparcStation4:
|
||||
The optimizer neglects to reload CPU registers after a setjmp() in
|
||||
complex functions (namely eval_instruction() in interpret.c). The
|
||||
workaround is to put the setjmp()-recover branch into a separate function
|
||||
and making sure that it can't be inlined (e.g. by calling it indirectly).
|
||||
|
||||
gcc 2.8.1 on Solaris 5.7; egcs 2.91.16 on SunOS 4.1.3_U1, and probably
|
||||
others:
|
||||
Compiling with optimization causes the compiler (not the assembler!) to
|
||||
fall into catatonia for the configuration test for a float/branch
|
||||
incompatibility. Workaround is to make sure that configure compiles this
|
||||
test without optimization.
|
||||
|
||||
gcc 2.9-beos-980929 on BeOS/x86:
|
||||
Compiling without optimization causes the compiler to crash on simulate.c
|
||||
|
||||
gcc 2.7.2.1-i486-linux on Linux 2.0.33:
|
||||
Optimizing compiles may pessimize the expression
|
||||
(svalue.type == x && svalue.x.closure_type == y)
|
||||
to 'comparison is always zero' if both fields share the same longword
|
||||
in memory (closure.c is one victim).
|
||||
Makeshift solution: Assigning one of the fields to a local variable
|
||||
causes the expression to produce the correct result.
|
||||
|
||||
gcc 1.36 on Next / NextStep 2.1 with flags '-g' / '-g -fomit_frame_pointer' :
|
||||
The calculated offset to a6 for parameter access in free_svalue() is wrong.
|
||||
Symptom: mud crashes early.
|
||||
Makeshift solution: use '-O -fomit-frame-pointer'
|
||||
|
||||
gcc 2.2.2 , when told to optimize interpret.c , usually dies with a segv
|
||||
or currupted internal data structures in cc1.
|
||||
|
||||
gcc 2.3.3 , when told to optimize lex.c , will garble the code for #include.
|
||||
Symptom: load_object will fail when #include is used, saying it can't
|
||||
#include the file.
|
||||
|
||||
gcc 2.x on 680x0 hardware: the large interpret.c switch table is built with
|
||||
unsigned short words, but is processed like signed short words.
|
||||
The special thing about 680x0 is that the switch in interpret.c is
|
||||
shorter than 64 KB.
|
||||
Symptoms: when LPC instructions are to be executed the code to which
|
||||
lies beyond the first 32 KB of the switch(), there is weird behaviour,
|
||||
a C-level illegal intruction or a crash with undetermined, although most
|
||||
times quite short, latency.
|
||||
Makeshift solution: fix the assembler code in interpret.s to handle
|
||||
unsigned short offsets.
|
||||
|
||||
NeXTStep 3.2 has a broken memcmp(), that will give different return values
|
||||
depending on alignment.
|
||||
The library that contained this broken memcmp() looks like this:
|
||||
-r-xr-xr-x 1 root 1012100 Sep 1 1993 libsys_s.B.shlib*
|
||||
quickfix: #define memcmp(a,b,l) (*(int*)(a) - *(int*)(b)) in closure.c and
|
||||
prolang.y, or a file included by these.
|
||||
|
||||
ULTRIX dec1 4.3 0 RISC needs <sys/types.h> to be included before <sys/stat.h>
|
619
src/Makefile.in
Normal file
619
src/Makefile.in
Normal file
|
@ -0,0 +1,619 @@
|
|||
# TODO: Add some of the symbols in here to configure
|
||||
# These lines are needed on some machines.
|
||||
MAKE=make
|
||||
SHELL=@CONFIG_SHELL@
|
||||
INSTALL=@INSTALL@
|
||||
mkinstalldirs=$(SHELL) @top_srcdir@/mkinstalldirs
|
||||
#
|
||||
CC=@CC@
|
||||
#
|
||||
YACC = @YACC@
|
||||
YACCTAB = @YACCTAB@
|
||||
#
|
||||
RM = rm -f
|
||||
MV = mv
|
||||
CP = cp
|
||||
#
|
||||
# some standard stuff...
|
||||
prefix= @prefix@
|
||||
exec_prefix= @exec_prefix@
|
||||
# currently unused:
|
||||
datarootdir = @datarootdir@
|
||||
#
|
||||
#
|
||||
# Set MUD_LIB to the directory which contains the mud data.
|
||||
MUD_LIB = @libdir@
|
||||
# Set MUD_LIB_INCLUDE to the directory where the driver include files
|
||||
# shall live.
|
||||
MUD_LIB_INCLUDE = @includedir@
|
||||
#
|
||||
# Set BINDIR to the directory where you want to install the executables.
|
||||
BINDIR = @bindir@
|
||||
#
|
||||
# Set ERQ_DIR to directory which contains the stuff which ERQ can
|
||||
# execute (hopefully) savely. Was formerly defined in config.h!
|
||||
ERQ_DIR= @libexecdir@
|
||||
#
|
||||
# Set MANDIR to the directory where to install the manpages.
|
||||
MANDIR= @mandir@
|
||||
#
|
||||
# Typical profiling, warning and optimizing options.
|
||||
# -p -DMARK: together they enable customized profiling of VM instructions.
|
||||
# MARK needs to be defined to a statement taking the
|
||||
# instruction code as parameter; additionally interpret.c will
|
||||
# #include "profile.h" for additional custom declarations.
|
||||
#
|
||||
# Additional profiling can be activated in config.h .
|
||||
#PROFIL=-pg -DMARK
|
||||
#PROFIL=-pg
|
||||
PROFIL=
|
||||
|
||||
# Enable warnings from the compiler, if wanted.
|
||||
NO_WARN= # no warning options - will work with all compilers :-)
|
||||
GCC_WARN= -Wall -Wshadow -Wparentheses # gcc settings
|
||||
CFG_WARN= @WCFLAGS@ # Warn options discovered by configure
|
||||
|
||||
WARN= $(CFG_WARN)
|
||||
|
||||
|
||||
# Optimization and source level debugging options.
|
||||
# adding a -fomit-frame-pointer on the NeXT (gcc version 1.93 (68k, MIT syntax))
|
||||
# will corrupt the driver.
|
||||
|
||||
HIGH_OPTIMIZE = @OCFLAGS@ # high optimization
|
||||
MED_OPTIMIZE= @MCFLAGS@ # medium optimization
|
||||
LOW_OPTIMIZE = @LCFLAGS@ # minimal optimization
|
||||
NO_OPTIMIZE= @DCFLAGS@ # no optimization; for frequent recompilations.
|
||||
|
||||
OPTIMIZE= $(@val_optimize@_OPTIMIZE)
|
||||
|
||||
#
|
||||
# Debugging options:
|
||||
# Debugging options should be set in config.h to guarantee a clean
|
||||
# recompile.
|
||||
#DEBUG = -DDEBUG # -DDEBUG_TELNET
|
||||
DEBUG=
|
||||
#
|
||||
MPATH=-DMUD_LIB='"$(MUD_LIB)"' -DBINDIR='"$(BINDIR)"' -DERQ_DIR='"$(ERQ_DIR)"'
|
||||
#
|
||||
CFLAGS=-DPROGNAME='"@PROGNAME@"' @EXTRA_CFLAGS@ $(OPTIMIZE) $(DEBUG) $(WARN) $(MPATH) $(PROFIL)
|
||||
#
|
||||
LIBS=@LIBS@ @PKGLIBS@
|
||||
#
|
||||
LDFLAGS=$(PROFIL) @LDFLAGS@
|
||||
#
|
||||
#Note that, if you use smalloc with SBRK_OK(which is the default), and
|
||||
#don't link statically, it could happen that the system malloc is linked
|
||||
#along with the one from smalloc; this combination is bound to cause crashes.
|
||||
MFLAGS = "BINDIR=$(BINDIR)" "MUD_LIB=$(MUD_LIB)"
|
||||
#
|
||||
SRC = access_check.c actions.c array.c backend.c bitstrings.c call_out.c \
|
||||
closure.c comm.c \
|
||||
dumpstat.c ed.c efuns.c files.c gcollect.c hash.c heartbeat.c \
|
||||
interpret.c \
|
||||
lex.c main.c mapping.c md5.c mempools.c mregex.c mstrings.c object.c \
|
||||
otable.c\
|
||||
parser.c parse.c pkg-alists.c pkg-idna.c \
|
||||
pkg-mccp.c pkg-mysql.c pkg-pcre.c \
|
||||
pkg-pgsql.c pkg-sqlite.c pkg-tls.c \
|
||||
ptmalloc.c port.c ptrtable.c \
|
||||
random.c regexp.c sha1.c simulate.c simul_efun.c stdstrings.c \
|
||||
strfuns.c structs.c sprintf.c swap.c wiz_list.c xalloc.c pkg-expat.c
|
||||
OBJ = access_check.o actions.o array.o backend.o bitstrings.o call_out.o \
|
||||
closure.o comm.o \
|
||||
dumpstat.o ed.o efuns.o files.o gcollect.o hash.o heartbeat.o \
|
||||
interpret.o \
|
||||
lex.o main.o mapping.o md5.o mempools.o mregex.o mstrings.o object.o \
|
||||
otable.o \
|
||||
parser.o parse.o pkg-alists.o pkg-idna.o \
|
||||
pkg-mccp.o pkg-mysql.o pkg-pcre.o \
|
||||
pkg-pgsql.o pkg-sqlite.o pkg-tls.o \
|
||||
ptmalloc.o port.o ptrtable.o \
|
||||
random.o regexp.o sha1.o simulate.o simul_efun.o stdstrings.o \
|
||||
strfuns.o structs.o sprintf.o swap.o wiz_list.o xalloc.o @ALLOCA@ \
|
||||
pkg-expat.o
|
||||
|
||||
all: make-patchlevel @PROGNAME@@EXEEXT@
|
||||
|
||||
@PROGNAME@@EXEEXT@: $(OBJ)
|
||||
$(CC) @OPTIMIZE_LINKING@ $(LDFLAGS) $(OBJ) -o $@ $(LIBS)
|
||||
|
||||
it: @PROGNAME@@EXEEXT@
|
||||
strip @PROGNAME@@EXEEXT@
|
||||
|
||||
docs: @PROGNAME@@EXEEXT@
|
||||
-help2man --name=@PROGNAME@ -N --help-option=--longhelp --include=../HELP --output=../@PROGNAME@.1 ./@PROGNAME@@EXEEXT@
|
||||
|
||||
install-all: install-driver install-headers install-utils
|
||||
|
||||
install: install-driver
|
||||
@echo "To install header files, use 'make install-headers'."
|
||||
@echo "To install utility programs (incl. erq), use 'make install-utils'."
|
||||
@echo "To install everything in one go, use 'make install-all'."
|
||||
|
||||
install-driver: @PROGNAME@@EXEEXT@ docs
|
||||
$(mkinstalldirs) $(BINDIR) $(MANDIR)/man1
|
||||
$(INSTALL) -c @PROGNAME@@EXEEXT@ $(BINDIR)/@PROGNAME@@EXEEXT@
|
||||
$(INSTALL) -c ../doc/man/@PROGNAME@.1 $(MANDIR)/man1/@PROGNAME@.1
|
||||
|
||||
install-headers:
|
||||
$(mkinstalldirs) $(MUD_LIB_INCLUDE)
|
||||
$(INSTALL) -c ../mudlib/sys/* $(MUD_LIB_INCLUDE)
|
||||
|
||||
install-utils:
|
||||
(cd util; $(MAKE) $(MFLAGS) install)
|
||||
|
||||
utils:
|
||||
(cd util; $(MAKE) $(MFLAGS))
|
||||
|
||||
lint: *.c
|
||||
lint *.c
|
||||
|
||||
clean:
|
||||
$(RM) $(YACCTAB)h $(YACCTAB)c make_func.c *.o mkfunc@EXEEXT@
|
||||
$(RM) dftables@EXEEXT@ pcre/chartables.c
|
||||
$(RM) stdstrings.c stdstrings.h
|
||||
$(RM) efun_defs.c instrs.h lang.y lang.h lang.c y.output tags TAGS
|
||||
$(RM) @PROGNAME@@EXEEXT@ core mudlib/core mudlib/debug.log
|
||||
(cd util ; echo "Cleaning in util." ; $(MAKE) clean)
|
||||
|
||||
distclean: clean
|
||||
$(RM) @PROGNAME@@EXEEXT@ config.status machine.h Makefile config.cache config.log
|
||||
$(RM) config.h config.status config.status.old
|
||||
$(RM) util/Makefile util/erq/Makefile
|
||||
|
||||
tags: $(SRC)
|
||||
ctags $(SRC)
|
||||
|
||||
TAGS: $(SRC)
|
||||
etags $(SRC)
|
||||
|
||||
patchlevel.h : make-patchlevel
|
||||
|
||||
make-patchlevel:
|
||||
./mk-patchlevel.sh
|
||||
|
||||
make_func.c: make_func.y
|
||||
$(YACC) make_func.y
|
||||
@MOVE_YACC_TAB@ make_func.c
|
||||
@CLEAN_YACC_TAB@
|
||||
|
||||
#mkfunc.o : mkfunc.c make_func.c driver.h config.h machine.h port.h
|
||||
# $(CC) $(CFLAGS) -c mkfunc.c
|
||||
|
||||
mkfunc@EXEEXT@: mkfunc.o hash.o exec.h
|
||||
$(CC) @OPTIMIZE_LINKING@ $(LDFLAGS) mkfunc.o hash.o -o mkfunc@EXEEXT@
|
||||
|
||||
dftables.o : pcre/dftables.c pcre/maketables.c pcre/config.h
|
||||
$(CC) $(CFLAGS) -c pcre/dftables.c -o dftables.o
|
||||
|
||||
dftables@EXEEXT@ : dftables.o
|
||||
$(CC) @OPTIMIZE_LINKING@ $(LDFLAGS) dftables.o -o dftables@EXEEXT@
|
||||
|
||||
lang.y: mkfunc@EXEEXT@ prolang.y config.h
|
||||
$(RM) lang.y
|
||||
./mkfunc@EXEEXT@ lang
|
||||
|
||||
efun_defs.c instrs.h: func_spec mkfunc@EXEEXT@ config.h machine.h
|
||||
$(RM) instrs.h
|
||||
$(RM) efun_defs.c
|
||||
./mkfunc@EXEEXT@ instrs
|
||||
|
||||
stdstrings.c stdstrings.h: string_spec mkfunc@EXEEXT@ config.h machine.h
|
||||
$(RM) stdstrings.c
|
||||
$(RM) stdstrings.h
|
||||
./mkfunc@EXEEXT@ strings
|
||||
|
||||
lang.c lang.h: lang.y
|
||||
$(YACC) -d -v lang.y
|
||||
@MOVE_YACC_TAB@ lang.c
|
||||
@CLEAN_YACC_TAB@
|
||||
$(MV) $(YACCTAB)h lang.h
|
||||
|
||||
pcre/chartables.c : dftables@EXEEXT@
|
||||
./dftables@EXEEXT@ pcre/chartables.c
|
||||
|
||||
#--------------------------------------------------------
|
||||
# The dependency generation uses the program 'mkdepend' and assumes GNUmake.
|
||||
|
||||
# Generated source files (overlaps with of SRC) which need to be
|
||||
# present for mkdepend to work.
|
||||
GENSRC = make_func.c stdstrings.c lang.c instrs.h pcre/chartables.c
|
||||
|
||||
# Macros for MkDepend:
|
||||
SKELETON = $(SRC) mkfunc.c pcre/dftables.c
|
||||
EXCEPT = -x efun_defs.c
|
||||
SELECT = -S instrs.h -S stdstrings.h -S make_func.c -S lang.c -S lang.h -S efun_defs.c
|
||||
|
||||
depend: $(SRC) $(GENSRC)
|
||||
@$(SHELL) -ec "if type mkdepend > /dev/null 2>&1; then \
|
||||
echo Updating dependencies.; \
|
||||
mkdepend $(SKELETON) -I. $(EXCEPT) -m -p .c:%n.o -fMakefile; \
|
||||
mkdepend $(SKELETON) -I. $(EXCEPT) $(SELECT) -m -p .c:%n.o -fMakefile; \
|
||||
echo Updating dependencies in Makefile.in.; \
|
||||
mkdepend $(SKELETON) -I. $(EXCEPT) -m -p .c:%n.o -fMakefile.in; \
|
||||
mkdepend $(SKELETON) -I. $(EXCEPT) $(SELECT) -m -p .c:%n.o -fMakefile.in; \
|
||||
else\
|
||||
echo mkdepend utility not available.; \
|
||||
fi"
|
||||
|
||||
.PHONY dependall: depend depend-generic
|
||||
|
||||
depend-generic: $(SRC) $(GENSRC)
|
||||
@$(SHELL) -ec "if type mkdepend > /dev/null 2>&1; then \
|
||||
echo Updating dependencies in hosts/be/Makefile.; \
|
||||
mkdepend $(SKELETON) -I. $(EXCEPT) -m -p .c:$$\(OBJ\)/%n.o -fhosts/be/Makefile; \
|
||||
mkdepend $(SKELETON) -I. $(EXCEPT) $(SELECT) -m -p .c:$$\(OBJ\)/%n.o -fhosts/be/Makefile; \
|
||||
else\
|
||||
echo mkdepend utility not available.; \
|
||||
fi"
|
||||
|
||||
|
||||
#--------------------------------------------------------
|
||||
# Dependencies, manual and automatic.
|
||||
|
||||
# --- DO NOT MODIFY THIS LINE -- AUTO-DEPENDS FOLLOW ---
|
||||
access_check.o : xalloc.h filestat.h comm.h access_check.h driver.h \
|
||||
svalue.h strfuns.h pkg-tls.h simulate.h typedefs.h config.h port.h \
|
||||
sent.h bytecode.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
actions.o : ../mudlib/sys/driver_hook.h ../mudlib/sys/commands.h xalloc.h \
|
||||
wiz_list.h svalue.h simulate.h sent.h stdstrings.h object.h mstrings.h \
|
||||
mapping.h interpret.h efuns.h dumpstat.h comm.h closure.h backend.h \
|
||||
array.h actions.h my-alloca.h typedefs.h driver.h strfuns.h bytecode.h \
|
||||
hash.h pkg-tls.h main.h port.h config.h hosts/unix.h hosts/be/be.h \
|
||||
machine.h
|
||||
|
||||
array.o : i-svalue_cmp.h xalloc.h wiz_list.h swap.h svalue.h simulate.h \
|
||||
stdstrings.h object.h mstrings.h mempools.h mapping.h main.h \
|
||||
interpret.h closure.h backend.h array.h my-alloca.h typedefs.h driver.h \
|
||||
strfuns.h sent.h bytecode.h hash.h port.h config.h hosts/unix.h \
|
||||
hosts/be/be.h machine.h
|
||||
|
||||
backend.o : ../mudlib/sys/debug_message.h ../mudlib/sys/driver_hook.h \
|
||||
xalloc.h wiz_list.h swap.h svalue.h stdstrings.h simulate.h random.h \
|
||||
otable.h object.h mstrings.h mregex.h mapping.h main.h lex.h \
|
||||
interpret.h heartbeat.h gcollect.h filestat.h exec.h ed.h comm.h \
|
||||
closure.h call_out.h array.h actions.h backend.h my-alloca.h typedefs.h \
|
||||
driver.h strfuns.h sent.h bytecode.h hash.h pkg-tls.h port.h config.h \
|
||||
hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
bitstrings.o : xalloc.h svalue.h simulate.h mstrings.h interpret.h \
|
||||
bitstrings.h typedefs.h driver.h strfuns.h sent.h bytecode.h hash.h \
|
||||
backend.h port.h config.h main.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
call_out.o : ../mudlib/sys/debug_info.h xalloc.h wiz_list.h swap.h svalue.h \
|
||||
strfuns.h stdstrings.h simulate.h object.h mstrings.h main.h \
|
||||
interpret.h gcollect.h exec.h comm.h closure.h backend.h array.h \
|
||||
actions.h call_out.h typedefs.h driver.h sent.h bytecode.h hash.h \
|
||||
pkg-tls.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
closure.o : i-svalue_cmp.h xalloc.h switch.h swap.h svalue.h structs.h \
|
||||
stdstrings.h simul_efun.h simulate.h prolang.h object.h mstrings.h \
|
||||
main.h lex.h interpret.h instrs.h exec.h backend.h array.h closure.h \
|
||||
my-alloca.h typedefs.h driver.h strfuns.h hash.h ptrtable.h sent.h \
|
||||
bytecode.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
comm.o : util/erq/erq.h ../mudlib/sys/input_to.h \
|
||||
../mudlib/sys/driver_hook.h ../mudlib/sys/comm.h xalloc.h wiz_list.h \
|
||||
swap.h svalue.h stdstrings.h simulate.h sent.h pkg-tls.h pkg-pgsql.h \
|
||||
pkg-mccp.h object.h mstrings.h main.h interpret.h gcollect.h filestat.h \
|
||||
exec.h ed.h closure.h array.h actions.h access_check.h comm.h \
|
||||
../mudlib/sys/telnet.h my-alloca.h typedefs.h driver.h strfuns.h \
|
||||
bytecode.h hash.h backend.h config.h port.h hosts/unix.h hosts/be/be.h \
|
||||
machine.h
|
||||
|
||||
dumpstat.o : xalloc.h svalue.h structs.h stdstrings.h simulate.h ptrtable.h \
|
||||
object.h mstrings.h mapping.h instrs.h filestat.h exec.h closure.h \
|
||||
array.h dumpstat.h typedefs.h driver.h strfuns.h hash.h sent.h \
|
||||
bytecode.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
ed.o : ../mudlib/sys/regexp.h xalloc.h svalue.h stdstrings.h simulate.h \
|
||||
object.h mstrings.h mregex.h main.h lex.h interpret.h gcollect.h \
|
||||
filestat.h comm.h actions.h ed.h typedefs.h driver.h strfuns.h sent.h \
|
||||
bytecode.h hash.h backend.h pkg-tls.h port.h config.h hosts/unix.h \
|
||||
hosts/be/be.h machine.h
|
||||
|
||||
efuns.o : ../mudlib/sys/time.h ../mudlib/sys/strings.h \
|
||||
../mudlib/sys/regexp.h ../mudlib/sys/objectinfo.h \
|
||||
../mudlib/sys/driver_hook.h ../mudlib/sys/debug_info.h xalloc.h \
|
||||
wiz_list.h svalue.h swap.h structs.h strfuns.h simulate.h stdstrings.h \
|
||||
sha1.h random.h ptrtable.h otable.h object.h mstrings.h mregex.h md5.h \
|
||||
mempools.h mapping.h main.h lex.h interpret.h heartbeat.h exec.h \
|
||||
dumpstat.h comm.h closure.h call_out.h backend.h array.h actions.h \
|
||||
efuns.h my-rusage.h my-alloca.h typedefs.h driver.h hash.h sent.h \
|
||||
bytecode.h my-stdint.h pkg-tls.h port.h config.h hosts/unix.h \
|
||||
hosts/be/be.h machine.h
|
||||
|
||||
files.o : ../mudlib/sys/files.h xalloc.h svalue.h stdstrings.h simulate.h \
|
||||
mstrings.h mempools.h main.h lex.h interpret.h filestat.h comm.h \
|
||||
array.h files.h my-alloca.h typedefs.h driver.h strfuns.h sent.h \
|
||||
bytecode.h hash.h backend.h pkg-tls.h port.h config.h hosts/unix.h \
|
||||
hosts/be/be.h machine.h
|
||||
|
||||
gcollect.o : ../mudlib/sys/driver_hook.h xalloc.h wiz_list.h swap.h \
|
||||
structs.h stdstrings.h simul_efun.h simulate.h sent.h random.h \
|
||||
ptrtable.h prolang.h pkg-pgsql.h parse.h otable.h object.h mstrings.h \
|
||||
mregex.h mempools.h mapping.h main.h lex.h instrs.h interpret.h \
|
||||
heartbeat.h filestat.h ed.h comm.h closure.h call_out.h backend.h \
|
||||
array.h actions.h gcollect.h typedefs.h driver.h svalue.h strfuns.h \
|
||||
hash.h exec.h bytecode.h pkg-tls.h port.h config.h hosts/unix.h \
|
||||
hosts/be/be.h machine.h
|
||||
|
||||
hash.o : hash.h
|
||||
|
||||
heartbeat.o : ../mudlib/sys/debug_info.h xalloc.h wiz_list.h svalue.h \
|
||||
strfuns.h simulate.h sent.h object.h mstrings.h interpret.h gcollect.h \
|
||||
exec.h comm.h backend.h array.h actions.h heartbeat.h typedefs.h \
|
||||
driver.h bytecode.h hash.h pkg-tls.h main.h port.h config.h \
|
||||
hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
interpret.o : ../mudlib/sys/trace.h ../mudlib/sys/debug_info.h \
|
||||
../mudlib/sys/driver_hook.h xalloc.h wiz_list.h switch.h swap.h \
|
||||
svalue.h structs.h stdstrings.h simul_efun.h simulate.h prolang.h \
|
||||
parse.h otable.h object.h mstrings.h mapping.h lex.h instrs.h \
|
||||
heartbeat.h gcollect.h filestat.h exec.h efuns.h ed.h comm.h closure.h \
|
||||
call_out.h backend.h array.h actions.h interpret.h my-alloca.h \
|
||||
typedefs.h driver.h strfuns.h hash.h ptrtable.h sent.h bytecode.h \
|
||||
pkg-tls.h main.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
lex.o : efun_defs.c ../mudlib/sys/driver_hook.h xalloc.h wiz_list.h \
|
||||
svalue.h strfuns.h stdstrings.h simul_efun.h simulate.h prolang.h \
|
||||
patchlevel.h object.h mstrings.h mempools.h main.h lang.h interpret.h \
|
||||
instrs.h hash.h gcollect.h filestat.h exec.h comm.h closure.h backend.h \
|
||||
array.h lex.h my-alloca.h typedefs.h driver.h ptrtable.h sent.h \
|
||||
bytecode.h pkg-tls.h port.h config.h hosts/unix.h hosts/be/be.h \
|
||||
machine.h
|
||||
|
||||
main.o : ../mudlib/sys/regexp.h pkg-mysql.h xalloc.h wiz_list.h swap.h \
|
||||
svalue.h stdstrings.h simul_efun.h simulate.h random.h pkg-tls.h \
|
||||
patchlevel.h otable.h object.h mstrings.h mregex.h mempools.h mapping.h \
|
||||
lex.h interpret.h gcollect.h filestat.h comm.h array.h backend.h main.h \
|
||||
my-alloca.h typedefs.h driver.h strfuns.h ptrtable.h exec.h sent.h \
|
||||
bytecode.h hash.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
mapping.o : i-svalue_cmp.h xalloc.h wiz_list.h svalue.h structs.h \
|
||||
simulate.h object.h mstrings.h main.h interpret.h gcollect.h closure.h \
|
||||
backend.h array.h mapping.h my-alloca.h typedefs.h driver.h strfuns.h \
|
||||
hash.h exec.h sent.h bytecode.h port.h config.h hosts/unix.h \
|
||||
hosts/be/be.h machine.h
|
||||
|
||||
md5.o : strfuns.h md5.h machine.h typedefs.h driver.h port.h config.h \
|
||||
hosts/unix.h hosts/be/be.h
|
||||
|
||||
mempools.o : ../mudlib/sys/debug_info.h xalloc.h svalue.h strfuns.h \
|
||||
simulate.h gcollect.h mempools.h driver.h typedefs.h sent.h bytecode.h \
|
||||
port.h config.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
mkfunc.o : make_func.c ../mudlib/sys/driver_hook.h hash.h exec.h \
|
||||
my-alloca.h driver.h bytecode.h typedefs.h port.h config.h hosts/unix.h \
|
||||
hosts/be/be.h machine.h
|
||||
|
||||
mregex.o : ../mudlib/sys/regexp.h ../mudlib/sys/driver_hook.h \
|
||||
../mudlib/sys/debug_info.h xalloc.h svalue.h strfuns.h simulate.h \
|
||||
regexp.h pkg-pcre.h mstrings.h main.h interpret.h hash.h gcollect.h \
|
||||
comm.h mregex.h driver.h typedefs.h sent.h bytecode.h pcre/pcre.h \
|
||||
backend.h pkg-tls.h port.h config.h hosts/unix.h hosts/be/be.h \
|
||||
machine.h
|
||||
|
||||
mstrings.o : ../mudlib/sys/debug_info.h xalloc.h svalue.h strfuns.h \
|
||||
stdstrings.h simulate.h main.h hash.h gcollect.h mstrings.h driver.h \
|
||||
typedefs.h sent.h bytecode.h port.h config.h hosts/unix.h hosts/be/be.h \
|
||||
machine.h
|
||||
|
||||
object.o : ../mudlib/sys/inherit_list.h ../mudlib/sys/include_list.h \
|
||||
../mudlib/sys/functionlist.h ../mudlib/sys/driver_hook.h xalloc.h \
|
||||
wiz_list.h svalue.h swap.h structs.h strfuns.h stdstrings.h \
|
||||
simul_efun.h simulate.h sent.h random.h ptrtable.h prolang.h otable.h \
|
||||
mstrings.h mempools.h mapping.h main.h lex.h instrs.h interpret.h \
|
||||
filestat.h comm.h closure.h backend.h array.h actions.h object.h \
|
||||
my-alloca.h typedefs.h driver.h ../mudlib/sys/lpctypes.h hash.h exec.h \
|
||||
bytecode.h pkg-tls.h port.h config.h hosts/unix.h hosts/be/be.h \
|
||||
machine.h
|
||||
|
||||
otable.o : ../mudlib/sys/debug_info.h xalloc.h svalue.h simulate.h \
|
||||
strfuns.h object.h mstrings.h hash.h gcollect.h backend.h otable.h \
|
||||
typedefs.h driver.h sent.h bytecode.h main.h port.h config.h \
|
||||
hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
parse.o : xalloc.h wiz_list.h svalue.h stdstrings.h simulate.h object.h \
|
||||
mstrings.h main.h lex.h interpret.h gcollect.h array.h actions.h \
|
||||
parse.h typedefs.h driver.h strfuns.h sent.h bytecode.h hash.h \
|
||||
backend.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
parser.o : lang.c ../mudlib/sys/driver_hook.h xalloc.h wiz_list.h switch.h \
|
||||
swap.h svalue.h structs.h stdstrings.h simul_efun.h simulate.h object.h \
|
||||
mstrings.h mapping.h main.h lex.h instrs.h interpret.h gcollect.h \
|
||||
exec.h closure.h backend.h array.h prolang.h my-alloca.h typedefs.h \
|
||||
driver.h strfuns.h hash.h ptrtable.h sent.h bytecode.h port.h config.h \
|
||||
hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
dftables.o : pcre/maketables.c pcre/internal.h pcre/pcre.h pcre/config.h
|
||||
|
||||
pkg-alists.o : i-svalue_cmp.h xalloc.h svalue.h simulate.h mstrings.h \
|
||||
main.h interpret.h array.h my-alloca.h pkg-alists.h typedefs.h driver.h \
|
||||
closure.h strfuns.h sent.h bytecode.h hash.h backend.h port.h config.h \
|
||||
hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
pkg-idna.o : ../mudlib/sys/idn.h xalloc.h simulate.h mstrings.h interpret.h \
|
||||
typedefs.h pkg-idna.h driver.h svalue.h strfuns.h sent.h bytecode.h \
|
||||
hash.h backend.h port.h config.h main.h hosts/unix.h hosts/be/be.h \
|
||||
machine.h
|
||||
|
||||
pkg-mccp.o : ../mudlib/sys/telnet.h xalloc.h svalue.h object.h mstrings.h \
|
||||
comm.h array.h pkg-mccp.h typedefs.h driver.h strfuns.h sent.h hash.h \
|
||||
pkg-tls.h simulate.h port.h config.h bytecode.h hosts/unix.h \
|
||||
hosts/be/be.h machine.h
|
||||
|
||||
pkg-mysql.o : xalloc.h svalue.h stdstrings.h simulate.h mstrings.h main.h \
|
||||
instrs.h interpret.h array.h pkg-mysql.h my-alloca.h typedefs.h \
|
||||
driver.h strfuns.h sent.h bytecode.h hash.h exec.h backend.h port.h \
|
||||
config.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
pkg-pcre.o : pcre/study.c pcre/maketables.c pcre/get.c pcre/pcre.c \
|
||||
simulate.h interpret.h pkg-pcre.h driver.h pcre/internal.h \
|
||||
pcre/chartables.c svalue.h strfuns.h sent.h bytecode.h typedefs.h \
|
||||
backend.h pcre/pcre.h port.h config.h pcre/config.h main.h hosts/unix.h \
|
||||
hosts/be/be.h machine.h
|
||||
|
||||
pkg-pgsql.o : ../mudlib/sys/pgsql.h xalloc.h stdstrings.h simulate.h \
|
||||
mstrings.h mapping.h main.h interpret.h instrs.h gcollect.h array.h \
|
||||
actions.h pkg-pgsql.h my-alloca.h typedefs.h driver.h svalue.h \
|
||||
strfuns.h sent.h bytecode.h hash.h backend.h exec.h port.h config.h \
|
||||
hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
pkg-sqlite.o : xalloc.h stdstrings.h object.h svalue.h simulate.h \
|
||||
mstrings.h interpret.h array.h my-alloca.h typedefs.h driver.h \
|
||||
strfuns.h sent.h bytecode.h hash.h backend.h port.h config.h main.h \
|
||||
hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
pkg-tls.o : ../mudlib/sys/tls.h xalloc.h svalue.h sha1.h object.h \
|
||||
mstrings.h main.h interpret.h comm.h array.h actions.h pkg-tls.h \
|
||||
machine.h driver.h strfuns.h typedefs.h my-stdint.h sent.h hash.h \
|
||||
bytecode.h backend.h simulate.h port.h config.h hosts/unix.h \
|
||||
hosts/be/be.h
|
||||
|
||||
port.o : hosts/crypt.c main.h backend.h my-rusage.h driver.h machine.h \
|
||||
typedefs.h port.h config.h hosts/unix.h hosts/be/be.h
|
||||
|
||||
ptmalloc.o : ptmalloc/malloc.c machine.h config.h ptmalloc/hooks.c \
|
||||
ptmalloc/arena.c ptmalloc/thread-m.h ptmalloc/malloc.h \
|
||||
ptmalloc/config.h
|
||||
|
||||
ptrtable.o : simulate.h mempools.h ptrtable.h driver.h svalue.h strfuns.h \
|
||||
sent.h bytecode.h typedefs.h port.h config.h hosts/unix.h hosts/be/be.h \
|
||||
machine.h
|
||||
|
||||
random.o : random.h driver.h port.h config.h hosts/unix.h hosts/be/be.h \
|
||||
machine.h
|
||||
|
||||
regexp.o : main.h xalloc.h simulate.h interpret.h regexp.h driver.h \
|
||||
typedefs.h svalue.h strfuns.h sent.h bytecode.h backend.h pkg-pcre.h \
|
||||
port.h config.h pcre/pcre.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
sha1.o : sha1.h my-stdint.h driver.h port.h config.h hosts/unix.h \
|
||||
hosts/be/be.h machine.h
|
||||
|
||||
simul_efun.o : xalloc.h swap.h svalue.h stdstrings.h simulate.h prolang.h \
|
||||
ptrtable.h object.h mstrings.h lex.h interpret.h gcollect.h exec.h \
|
||||
array.h simul_efun.h my-alloca.h typedefs.h driver.h strfuns.h sent.h \
|
||||
bytecode.h hash.h backend.h port.h config.h main.h hosts/unix.h \
|
||||
hosts/be/be.h machine.h
|
||||
|
||||
simulate.o : ../mudlib/sys/rtlimits.h ../mudlib/sys/regexp.h \
|
||||
../mudlib/sys/files.h ../mudlib/sys/driver_hook.h \
|
||||
../mudlib/sys/debug_info.h xalloc.h wiz_list.h svalue.h swap.h \
|
||||
structs.h strfuns.h stdstrings.h simul_efun.h sent.h prolang.h \
|
||||
pkg-sqlite.h pkg-tls.h otable.h object.h mstrings.h mregex.h mempools.h \
|
||||
mapping.h main.h lex.h interpret.h heartbeat.h gcollect.h filestat.h \
|
||||
ed.h comm.h closure.h call_out.h backend.h array.h actions.h simulate.h \
|
||||
my-alloca.h typedefs.h driver.h hash.h exec.h ptrtable.h bytecode.h \
|
||||
port.h config.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
sprintf.o : xalloc.h swap.h svalue.h structs.h stdstrings.h simul_efun.h \
|
||||
simulate.h sent.h random.h ptrtable.h object.h mstrings.h mapping.h \
|
||||
main.h interpret.h comm.h closure.h array.h actions.h sprintf.h \
|
||||
my-alloca.h typedefs.h driver.h strfuns.h hash.h exec.h bytecode.h \
|
||||
backend.h pkg-tls.h port.h config.h hosts/unix.h hosts/be/be.h \
|
||||
machine.h
|
||||
|
||||
stdstrings.o : mstrings.h stdstrings.h typedefs.h driver.h hash.h port.h \
|
||||
config.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
strfuns.o : xalloc.h svalue.h stdstrings.h simulate.h object.h mstrings.h \
|
||||
mapping.h main.h interpret.h comm.h strfuns.h my-alloca.h typedefs.h \
|
||||
driver.h sent.h bytecode.h hash.h backend.h pkg-tls.h port.h config.h \
|
||||
hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
structs.o : ../mudlib/sys/struct_info.h ../mudlib/sys/debug_info.h xalloc.h \
|
||||
wiz_list.h stdstrings.h simulate.h object.h mstrings.h mapping.h main.h \
|
||||
interpret.h gcollect.h exec.h array.h structs.h driver.h \
|
||||
../mudlib/sys/lpctypes.h svalue.h strfuns.h typedefs.h sent.h \
|
||||
bytecode.h hash.h backend.h port.h config.h hosts/unix.h hosts/be/be.h \
|
||||
machine.h
|
||||
|
||||
swap.o : ../mudlib/sys/debug_info.h xalloc.h wiz_list.h svalue.h structs.h \
|
||||
strfuns.h stdstrings.h simul_efun.h simulate.h random.h prolang.h \
|
||||
otable.h object.h mstrings.h mempools.h mapping.h main.h interpret.h \
|
||||
gcollect.h comm.h closure.h backend.h array.h swap.h typedefs.h \
|
||||
driver.h hash.h exec.h ptrtable.h sent.h bytecode.h pkg-tls.h port.h \
|
||||
config.h hosts/unix.h hosts/be/be.h machine.h
|
||||
|
||||
wiz_list.o : xalloc.h svalue.h stdstrings.h simulate.h object.h mstrings.h \
|
||||
mapping.h main.h interpret.h gcollect.h backend.h array.h \
|
||||
../mudlib/sys/wizlist.h wiz_list.h my-alloca.h typedefs.h driver.h \
|
||||
strfuns.h sent.h bytecode.h hash.h port.h config.h hosts/unix.h \
|
||||
hosts/be/be.h machine.h
|
||||
|
||||
xalloc.o : xptmalloc.c sysmalloc.c slaballoc.c smalloc.c mstrings.h \
|
||||
object.h exec.h simulate.h interpret.h gcollect.h backend.h xalloc.h \
|
||||
driver.h ../mudlib/sys/debug_info.h ptmalloc/malloc.h svalue.h \
|
||||
stdstrings.h sysmalloc.h array.h slaballoc.h typedefs.h smalloc.h \
|
||||
hash.h sent.h bytecode.h strfuns.h main.h port.h config.h hosts/unix.h \
|
||||
hosts/be/be.h machine.h
|
||||
|
||||
# --- DO NOT MODIFY THIS LINE -- AUTO-DEPENDS PRECEDE ---
|
||||
# --- DO NOT MODIFY THIS LINE -- SELECTED AUTO-DEPENDS FOLLOW ---
|
||||
actions.o : stdstrings.h
|
||||
|
||||
array.o : stdstrings.h
|
||||
|
||||
backend.o : stdstrings.h
|
||||
|
||||
call_out.o : stdstrings.h
|
||||
|
||||
closure.o : stdstrings.h instrs.h
|
||||
|
||||
comm.o : stdstrings.h
|
||||
|
||||
dumpstat.o : stdstrings.h instrs.h
|
||||
|
||||
ed.o : stdstrings.h
|
||||
|
||||
efuns.o : stdstrings.h
|
||||
|
||||
files.o : stdstrings.h
|
||||
|
||||
gcollect.o : stdstrings.h instrs.h
|
||||
|
||||
interpret.o : stdstrings.h instrs.h
|
||||
|
||||
lex.o : efun_defs.c stdstrings.h lang.h instrs.h
|
||||
|
||||
main.o : stdstrings.h
|
||||
|
||||
mkfunc.o : make_func.c
|
||||
|
||||
mstrings.o : stdstrings.h
|
||||
|
||||
object.o : stdstrings.h instrs.h
|
||||
|
||||
parse.o : stdstrings.h
|
||||
|
||||
parser.o : lang.c stdstrings.h instrs.h
|
||||
|
||||
pkg-mysql.o : stdstrings.h instrs.h
|
||||
|
||||
pkg-pgsql.o : stdstrings.h instrs.h
|
||||
|
||||
pkg-sqlite.o : stdstrings.h
|
||||
|
||||
simul_efun.o : stdstrings.h
|
||||
|
||||
simulate.o : stdstrings.h
|
||||
|
||||
sprintf.o : stdstrings.h
|
||||
|
||||
stdstrings.o : stdstrings.h
|
||||
|
||||
strfuns.o : stdstrings.h
|
||||
|
||||
structs.o : stdstrings.h
|
||||
|
||||
swap.o : stdstrings.h
|
||||
|
||||
wiz_list.o : stdstrings.h
|
||||
|
||||
xalloc.o : stdstrings.h
|
||||
|
||||
# --- DO NOT MODIFY THIS LINE -- SELECTED AUTO-DEPENDS PRECEDE ---
|
491
src/access_check.c
Normal file
491
src/access_check.c
Normal file
|
@ -0,0 +1,491 @@
|
|||
/*---------------------------------------------------------------------------
|
||||
* IP/time based access control.
|
||||
*
|
||||
* Copyright (C) 1995 by Joern Rennecke.
|
||||
*---------------------------------------------------------------------------
|
||||
* Access to the game is based on the user's IP address and the current time.
|
||||
* These are matched against a set of rules and if a match is detected, a
|
||||
* proper message is sent back and the connection is shutdown.
|
||||
*
|
||||
* This facility is active only if ACCESS_CONTROL has been defined in config.h
|
||||
* If ACCESS_LOG is defined in config.h, all checks and their results are
|
||||
* logged by comm.c in the specified file.
|
||||
*
|
||||
* The rules are read from the file ACCESS_FILE (defined in config.h,
|
||||
* typically "ACCESS.ALLOW") which resides in the mudlib. Every line specifies
|
||||
* one rule and has to follow the syntax given below. Lines with a '#' as
|
||||
* first character count as comments and are ignored, as are lines which
|
||||
* do not conform to the rule syntax (but except for empty lines this should
|
||||
* be relied upon).
|
||||
*
|
||||
* The syntax for a rule is (no leading whitespace allowed!):
|
||||
*
|
||||
* <ipnum>:[p<port>]:<class>:<max>:<start>:<end>:<text>
|
||||
* <ipnum>:[p<port>]:<class>:<max>:h<hours>:w<days>:m=<text>
|
||||
*
|
||||
* where
|
||||
* ipnum: <byte>.<byte>.<byte>.<byte>, with byte = * or number
|
||||
* There is only loose error checking - specifying an illegal
|
||||
* address will have interesting consequences, but would
|
||||
* most likely cause no error to occur.
|
||||
* port: the port number to which the connection is made. Omission
|
||||
* means 'any port'.
|
||||
* class: number
|
||||
* max: the maximum number of users, a number. The value -1 allows
|
||||
* an unlimited number of users.
|
||||
* start: hour this rule starts to be valid (0..23).
|
||||
* end: hour this rule ceases to be valid (0..23).
|
||||
* Setting both start and end to 0 skips any time check.
|
||||
* hours: hours this rule is valid.
|
||||
* This form allows several entries, separated with a ','.
|
||||
* Every entry can be a single hour (0..23), or a range in the
|
||||
* form '<start>-<end>'
|
||||
* Omitting the entry skips any time check.
|
||||
* days: the days this rule is valid.
|
||||
* The syntax is similar to <hours> except for the
|
||||
* allowable values: the days Sunday..Saturday are given as
|
||||
* the numbers 0..6.
|
||||
* Omitting the entry skips any day check.
|
||||
* text: string to send if the rule matches.
|
||||
*
|
||||
* A class is defined by the first rule using it's number. This
|
||||
* definition specifies the allowable <max>imum of users and the <text>
|
||||
* to send. Subsequent rules for the same class just add new ipnumber/
|
||||
* time rules, but don't change <max> or <text>
|
||||
*
|
||||
* ORDER MATTERS. That means if you allow 129.*.*.*, you have to put
|
||||
* any restrictions on 129.132.*.* BEFORE this rule.
|
||||
*
|
||||
* Addresses not matching any rule at all are not allowed. To get around
|
||||
* this, add an appropriate 'allow-all' rule *.*.*.* at the very end.
|
||||
*
|
||||
* An example rulefile:
|
||||
*
|
||||
* # SPARC cluster has access denied. Class 1
|
||||
* 129.132.122.*:1:0:0:0:LPMUD access denied for your cluster.
|
||||
*
|
||||
* # CALL-1A0 has access limited to some maximum, for now 5 logins. Class 2
|
||||
* 129.132.106.*:2:5:8:20:Sorry, LPMUD is currently full.
|
||||
*
|
||||
* # CALL-1A0 at all other times, its a 10 limit.
|
||||
* # Due to the rule order, this is effectively limited to times
|
||||
* # outside 8-20.
|
||||
* 129.132.106.*:3:10:0:0:Sorry, LPMUD is currently full.
|
||||
*
|
||||
* # No more than 5 users allowed from localhost while working hours :-)
|
||||
* 127.0.0.1:42:5:h8-12,13-18:w1-5:m=Pick a better time.
|
||||
*
|
||||
* # Everybody else is welcome.
|
||||
* *.*.*.*:0:-1:0:0:This message should never be printed.
|
||||
*
|
||||
* The rule file is (re)read whenever the gamedriver detects a change in its
|
||||
* timestamp.
|
||||
*
|
||||
* TODO: Make ACCESS_CONTROL a runtime option, also, when the file is
|
||||
* TODO:: missing on driver startup (and just then), allow every access.
|
||||
* TODO:: Alternatively, this could be made an
|
||||
* TODO:: efun "string|int access_control(file, [interactive])" to be used
|
||||
* TODO:: from TODO:: master.c::connect().
|
||||
* TODO:: Or a driver hook with the settings "file", ({ "file", "logfile" })
|
||||
* TODO:: and #'function(ip-address, port).
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "driver.h"
|
||||
|
||||
#if defined(ACCESS_CONTROL)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#include "access_check.h"
|
||||
|
||||
#include "comm.h"
|
||||
#include "filestat.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#undef DEBUG_ACCESS_CHECK /* define to activate debug output */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
#define MAX_MESSAGE_LENGTH 256
|
||||
|
||||
/* IP address/time rules, kept in a linked list.
|
||||
* Every structure describes one rule, with a reference to the
|
||||
* corresponding class structure.
|
||||
*/
|
||||
static struct access_address {
|
||||
uint32 addr, mask; /* The IP address and a mask for the interesting parts */
|
||||
int32 port; /* The port number (positive), or -1 for 'any port' */
|
||||
int32 hour_mask; /* Bitmask: at which times is this rule valid? */
|
||||
int32 wday_mask; /* Bitmask: at which days is this rule valid? */
|
||||
struct access_class *class; /* The corresponding class */
|
||||
struct access_address *next;
|
||||
} *all_access_addresses = NULL;
|
||||
|
||||
/* Class descriptions, kept in a linked list.
|
||||
* The structure is allocated big enough to keep the full message, the
|
||||
* 8 characters listed in the definition are just a placeholder.
|
||||
*/
|
||||
static struct access_class {
|
||||
long id; /* Class ID */
|
||||
mp_int max_usage, usage; /* Max and current number of users */
|
||||
struct access_class *next;
|
||||
char message[8]; /* Placeholder for the message text buffer */
|
||||
} *all_access_classes = NULL;
|
||||
|
||||
static time_t last_read_time = 0;
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static struct access_class *
|
||||
find_access_class (struct sockaddr_in *full_addr, int port)
|
||||
|
||||
/* Find and return the class structure for the given IP <full_addr> at
|
||||
* the current time. Return NULL if no rule covers the IP at this time.
|
||||
*/
|
||||
|
||||
{
|
||||
uint32 addr;
|
||||
struct access_address *aap;
|
||||
time_t seconds;
|
||||
struct tm *tm_p;
|
||||
|
||||
#ifdef DEBUG_ACCESS_CHECK
|
||||
fprintf(stderr, "find_class for '%s':%d\n"
|
||||
, inet_ntoa(*(struct in_addr*)&full_addr->sin_addr)
|
||||
, port);
|
||||
#endif
|
||||
#ifndef USE_IPV6
|
||||
addr = full_addr->sin_addr.s_addr;
|
||||
#else
|
||||
addr = (uint32) full_addr->sin_addr.s_addr;
|
||||
/* TODO: DANGER: The above cast might break under IPv6 */
|
||||
#endif
|
||||
tm_p = NULL;
|
||||
for (aap = all_access_addresses; aap; aap = aap->next) {
|
||||
#ifdef DEBUG_ACCESS_CHECK
|
||||
fprintf(stderr, " '%s':%ld, %ld %ld\n",
|
||||
inet_ntoa(*(struct in_addr*)&aap->addr),
|
||||
aap->port,
|
||||
(long)aap->class->max_usage, (long)aap->class->usage);
|
||||
#endif
|
||||
if (aap->port >= 0 && aap->port != port)
|
||||
continue;
|
||||
if ((aap->addr ^ addr) & aap->mask)
|
||||
continue;
|
||||
if (aap->wday_mask >= 0) {
|
||||
if (!tm_p) {
|
||||
time(&seconds);
|
||||
tm_p = localtime(&seconds);
|
||||
#ifdef DEBUG_ACCESS_CHECK
|
||||
fprintf(stderr, " h:%d w:%d\n", tm_p->tm_hour, tm_p->tm_wday);
|
||||
#endif
|
||||
}
|
||||
if ( !((1 << tm_p->tm_hour) & aap->hour_mask) )
|
||||
continue;
|
||||
if ( !((1 << tm_p->tm_wday) & aap->wday_mask) )
|
||||
continue;
|
||||
}
|
||||
#ifdef DEBUG_ACCESS_CHECK
|
||||
fprintf(stderr, " found\n");
|
||||
#endif
|
||||
return aap->class;
|
||||
}
|
||||
#ifdef DEBUG_ACCESS_CHECK
|
||||
fprintf(stderr, " not found\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void
|
||||
add_access_entry (struct sockaddr_in *full_addr, int login_port, long *idp)
|
||||
|
||||
/* Find the class structure for <full_addr> and increments its count
|
||||
* of users. The id of the class is put into *idp.
|
||||
* If there is no class, *idp is not changed.
|
||||
*
|
||||
* This function is called after the ACCESS_FILE has been (re-)read
|
||||
* to reinitialize the current class usage counts.
|
||||
*/
|
||||
|
||||
{
|
||||
struct access_class *acp;
|
||||
|
||||
acp = find_access_class(full_addr, login_port);
|
||||
if (acp) {
|
||||
acp->usage++;
|
||||
*idp = acp->id;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void
|
||||
read_access_file (void)
|
||||
|
||||
/* Read and parse the ACCESS_FILE, (re)creating all the datastructures.
|
||||
* After the file has been read, the usage counts will be updated by
|
||||
* calling comm::refresh_access_data, passing add_access_entry() as
|
||||
* callback.
|
||||
*/
|
||||
|
||||
{
|
||||
FILE *infp;
|
||||
struct access_address *aap, *next_aap, **last;
|
||||
struct access_class *acp, *next_acp;
|
||||
char message[MAX_MESSAGE_LENGTH];
|
||||
int i;
|
||||
int32 addr, mask;
|
||||
|
||||
/* Free the old datastructures */
|
||||
for (aap = all_access_addresses; aap; aap = next_aap) {
|
||||
next_aap = aap->next;
|
||||
pfree((char *)aap);
|
||||
}
|
||||
for (acp = all_access_classes; acp; acp = next_acp) {
|
||||
next_acp = acp->next;
|
||||
pfree((char *)acp);
|
||||
}
|
||||
all_access_classes = NULL;
|
||||
|
||||
infp = fopen(ACCESS_FILE, "r");
|
||||
if (!infp)
|
||||
perror("driver: Can't read access file '" ACCESS_FILE "'");
|
||||
FCOUNT_READ(ACCESS_FILE);
|
||||
last = &all_access_addresses;
|
||||
/* *last will be set to NULL at the end, so no dangling pointer
|
||||
* will exist.
|
||||
*/
|
||||
|
||||
/* The parse loop; it will terminate on file end or an error.
|
||||
* Every rule is parsed in four iterations: the first three read
|
||||
* the first bytes of the IP address, the fourth and last one
|
||||
* everything else.
|
||||
* If an address not specified in exactly 4 bytes, you will get
|
||||
* nonsense, but no error message.
|
||||
*/
|
||||
if (infp) for(addr = mask = 0;;) {
|
||||
long max_usage, class_id, port;
|
||||
int first_hour, last_hour, m;
|
||||
|
||||
/* Parse the next IP address byte, i.e. everything up to the
|
||||
* next . or : .
|
||||
*/
|
||||
addr <<= 8;
|
||||
mask <<= 8;
|
||||
m = fscanf(infp, "%9[^.:\n]%[.:]", message, message+12);
|
||||
if (m != 2 || *message == '#')
|
||||
{
|
||||
do {
|
||||
i = fgetc(infp);
|
||||
if (i == EOF)
|
||||
goto file_end;
|
||||
} while(i != '\n');
|
||||
addr = mask = 0;
|
||||
continue;
|
||||
}
|
||||
if (*message != '*') {
|
||||
int j;
|
||||
j = atoi(message);
|
||||
if ((unsigned int)j > 0xff)
|
||||
break;
|
||||
addr += j;
|
||||
mask += 0xff;
|
||||
}
|
||||
if (message[12] == '.') /* Then another byte follows */
|
||||
continue;
|
||||
|
||||
/* The ip-number may be followed with a port specification */
|
||||
i = fscanf(infp, "p%ld:", &port);
|
||||
if (!i)
|
||||
port = -1;
|
||||
|
||||
/* Parse the time specs next. Start by trying the first (old)
|
||||
* format.
|
||||
*/
|
||||
max_usage = 0;
|
||||
message[0] = '\0';
|
||||
|
||||
i = fscanf(infp, "%ld:%ld:%d:%d:",
|
||||
&class_id, &max_usage, &first_hour, &last_hour);
|
||||
if (!i)
|
||||
break;
|
||||
|
||||
aap = pxalloc(sizeof *aap);
|
||||
if (!aap)
|
||||
break;
|
||||
*last = aap;
|
||||
aap->addr = htonl(addr);
|
||||
aap->mask = htonl(mask);
|
||||
aap->port = port;
|
||||
aap->wday_mask = -1; /* Default: valid on every day */
|
||||
|
||||
if (i == 4) { /* Old format */
|
||||
if (first_hour || last_hour) {
|
||||
aap->wday_mask = 0x7f;
|
||||
if (first_hour <= last_hour) {
|
||||
aap->hour_mask = (2 << last_hour) - (1 << first_hour);
|
||||
} else {
|
||||
aap->hour_mask = -(1 << first_hour) + (2 << last_hour) - 1;
|
||||
}
|
||||
}
|
||||
} else if (i == 2) { /* New format */
|
||||
char c, c2[2];
|
||||
int32 *maskp;
|
||||
|
||||
for (;;) {
|
||||
c = 'm';
|
||||
fscanf(infp, "%c %1[=]", &c, c2);
|
||||
switch(c)
|
||||
{
|
||||
case 'w':
|
||||
maskp = &aap->wday_mask;
|
||||
goto get_mask;
|
||||
|
||||
case 'h':
|
||||
maskp = &aap->hour_mask;
|
||||
|
||||
get_mask:
|
||||
mask = 0;
|
||||
do {
|
||||
int j, k;
|
||||
|
||||
*c2 = '\0';
|
||||
if (!fscanf(infp, "%d %1[-,:] ", &j, c2))
|
||||
break;
|
||||
if (*c2 == '-') {
|
||||
k = 24;
|
||||
fscanf(infp, "%d %1[,:] ", &k, c2);
|
||||
if (j <= k) {
|
||||
mask |= (2 << k) - (1 << j);
|
||||
} else {
|
||||
mask |= -(1 << j) + (2 << k) - 1;
|
||||
}
|
||||
} else {
|
||||
mask |= 1 << j;
|
||||
}
|
||||
} while (*c2 == ',');
|
||||
*maskp = mask;
|
||||
aap->wday_mask &= 0x7f; /* make sure it's not negative */
|
||||
continue;
|
||||
|
||||
default:
|
||||
ungetc(c, infp);
|
||||
/* FALLTHROUGH */
|
||||
case 'm':
|
||||
break;
|
||||
} /* switch */
|
||||
|
||||
break;
|
||||
} /* for */
|
||||
} /* if (i) */
|
||||
|
||||
/* The rest of the line is the message to print.
|
||||
*/
|
||||
fgets(message, (int)sizeof(message)-1, infp);
|
||||
message[sizeof(message) - 1] = '\0';
|
||||
|
||||
/* Check if this rule creates a new class. If yes, allocate
|
||||
* a new structure and assign message text and usage to it.
|
||||
*/
|
||||
for (acp = all_access_classes; acp; acp = acp->next) {
|
||||
if (acp->id == class_id)
|
||||
break;
|
||||
}
|
||||
if (!acp) {
|
||||
size_t len;
|
||||
len = strlen(message);
|
||||
if (len && message[len-1] == '\n')
|
||||
message[--len] = '\0';
|
||||
acp = pxalloc(sizeof *acp - sizeof acp->message + 1 + len);
|
||||
if (!acp) {
|
||||
pfree((char *)aap);
|
||||
break;
|
||||
}
|
||||
acp->id = class_id;
|
||||
acp->max_usage = max_usage == -1 ? (mp_int)MAXINT : max_usage;
|
||||
acp->usage = 0;
|
||||
strcpy(acp->message, message);
|
||||
acp->next = all_access_classes;
|
||||
all_access_classes = acp;
|
||||
}
|
||||
|
||||
/* Finishing touches. */
|
||||
aap->class = acp;
|
||||
last = &aap->next;
|
||||
addr = mask = 0;
|
||||
}
|
||||
file_end: /* emergency exit from the loop */
|
||||
|
||||
/* Terminate the address list properly, then refresh the data */
|
||||
*last = NULL;
|
||||
refresh_access_data(add_access_entry);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
char *
|
||||
allow_host_access (struct sockaddr_in *full_addr, int login_port, long *idp)
|
||||
|
||||
/* Check if the IP address <full_addr> is allowed access at the current
|
||||
* time. Return NULL if access is granted, else an error message.
|
||||
*
|
||||
* If access is allowed, *idp is set to the corresponding class id; this
|
||||
* information is used later to re-initialize the class structures after
|
||||
* a re-read of the ACCESS_FILE.
|
||||
*
|
||||
* The ACCESS_FILE is read by this function if it has been changed.
|
||||
*/
|
||||
|
||||
{
|
||||
struct stat statbuf;
|
||||
struct access_class *acp;
|
||||
|
||||
if (ixstat(ACCESS_FILE, &statbuf))
|
||||
perror("driver: Can't stat access file '" ACCESS_FILE "'");
|
||||
else if (statbuf.st_mtime > last_read_time) {
|
||||
last_read_time = statbuf.st_mtime;
|
||||
read_access_file();
|
||||
}
|
||||
|
||||
acp = find_access_class(full_addr, login_port);
|
||||
if (acp) {
|
||||
if (acp->usage >= acp->max_usage)
|
||||
return acp->message;
|
||||
acp->usage++;
|
||||
*idp = acp->id;
|
||||
return NULL;
|
||||
}
|
||||
return "No matching entry";
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void
|
||||
release_host_access (long num)
|
||||
|
||||
/* One user from the class <num> logged out, update the class structure
|
||||
* accordingly.
|
||||
*/
|
||||
|
||||
{
|
||||
struct access_class *acp;
|
||||
|
||||
#ifdef DEBUG_ACCESS_CHECK
|
||||
fprintf(stderr, "release_host_access %ld called.\n", num);
|
||||
#endif
|
||||
for (acp = all_access_classes; acp; acp = acp->next) {
|
||||
if (acp->id != num)
|
||||
continue;
|
||||
acp->usage--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ACCESS_CONTROL */
|
||||
|
||||
/***************************************************************************/
|
||||
|
17
src/access_check.h
Normal file
17
src/access_check.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef ACCESS_CHECK_H__
|
||||
#define ACCESS_CHECK_H__ 1
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(ACCESS_CONTROL)
|
||||
|
||||
#include "driver.h"
|
||||
#include "comm.h"
|
||||
|
||||
extern char * allow_host_access(struct sockaddr_in *full_addr, int, long *idp);
|
||||
extern void release_host_access(long num);
|
||||
|
||||
#endif /* ACCESS_CONTROL */
|
||||
|
||||
#endif /* ACCESS_CHECK_H__ */
|
||||
|
2787
src/actions.c
Normal file
2787
src/actions.c
Normal file
File diff suppressed because it is too large
Load diff
42
src/actions.h
Normal file
42
src/actions.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
#ifndef ACTIONS_H__
|
||||
#define ACTIONS_H__ 1
|
||||
|
||||
#include "driver.h"
|
||||
|
||||
#include "typedefs.h" /* object_t */
|
||||
|
||||
/* --- Variables --- */
|
||||
|
||||
extern object_t *command_giver;
|
||||
extern p_int alloc_action_sent;
|
||||
|
||||
/* --- Prototypes --- */
|
||||
|
||||
extern void free_action_temporaries(void);
|
||||
extern void free_action_sent(action_t *p);
|
||||
extern void remove_action_sent(object_t *ob, object_t *player);
|
||||
extern void remove_shadow_action_sent(object_t *ob, object_t *player);
|
||||
extern void remove_environment_sent(object_t *player);
|
||||
extern void remove_shadow_actions (object_t *shadow, object_t *target);
|
||||
|
||||
extern void restore_command_context (rt_context_t *context);
|
||||
extern Bool execute_command (char *str, object_t *ob);
|
||||
extern svalue_t *v_add_action(svalue_t *sp, int num_arg);
|
||||
extern svalue_t *v_command(svalue_t *sp, int num_arg);
|
||||
extern svalue_t *f_disable_commands(svalue_t *sp);
|
||||
extern svalue_t *f_enable_commands(svalue_t *sp);
|
||||
extern svalue_t *f_execute_command(svalue_t *sp);
|
||||
extern svalue_t *f_living(svalue_t *sp);
|
||||
extern svalue_t *f_notify_fail(svalue_t *sp);
|
||||
extern svalue_t *f_query_notify_fail(svalue_t *sp);
|
||||
extern svalue_t *f_query_actions(svalue_t *sp);
|
||||
extern svalue_t *f_query_verb(svalue_t *sp);
|
||||
extern svalue_t *f_query_command(svalue_t *sp);
|
||||
extern svalue_t *f_command_stack_depth(svalue_t *sp);
|
||||
extern svalue_t *f_command_stack(svalue_t *sp);
|
||||
extern svalue_t *f_set_modify_command(svalue_t *sp);
|
||||
extern svalue_t *f_set_this_player(svalue_t *sp);
|
||||
extern svalue_t *f_remove_action(svalue_t *sp);
|
||||
extern svalue_t *f_match_command(svalue_t * sp);
|
||||
|
||||
#endif /* ACTIONS_H__ */
|
219
src/alloca.c
Normal file
219
src/alloca.c
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*---------------------------------------------------------------------------
|
||||
* Gamedriver alloca -- a portable alloca() implementation
|
||||
* Based on the public-domain version by D.A. Gwyn.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
* This implementation of the PWB library alloca() function,
|
||||
* which is used to allocate space off the run-time stack so
|
||||
* that it is automatically reclaimed upon procedure exit,
|
||||
* was inspired by discussions with J. Q. Johnson of Cornell
|
||||
* and later extended by Lars Duening.
|
||||
*
|
||||
* It should work under any C implementation that uses an
|
||||
* actual procedure stack (as opposed to a linked list of
|
||||
* frames). There are some preprocessor constants that can
|
||||
* be defined when compiling for your specific system, for
|
||||
* improved efficiency; however, the defaults should be okay.
|
||||
*
|
||||
* The general concept of this implementation is to keep
|
||||
* track of all alloca()-allocated blocks, and reclaim any
|
||||
* that are found to be deeper in the stack than the current
|
||||
* invocation. This heuristic does not reclaim storage as
|
||||
* soon as it becomes invalid, but it will do so eventually.
|
||||
*
|
||||
* As a special case, alloca(0) reclaims storage without
|
||||
* allocating any, including storage 'cached' by the implementation
|
||||
* for fast reuse. It is a good idea to use alloca(0) in
|
||||
* your main control loop, etc. to force garbage collection.
|
||||
*
|
||||
* As opposed to the original implementaion using malloc()/free(),
|
||||
* this version utilizes the 'mempools' module to allocate the memory.
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mempools.h"
|
||||
|
||||
typedef void *pointer; /* generic pointer type */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/* Define STACK_DIRECTION if you know the direction of stack
|
||||
* growth for your system; otherwise it will be automatically
|
||||
* deduced at run-time.
|
||||
*
|
||||
* STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
* STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
* STACK_DIRECTION = 0 => direction of growth unknown
|
||||
*/
|
||||
|
||||
#if defined(AMIGA)
|
||||
# define STACK_DIRECTION -1
|
||||
#endif
|
||||
|
||||
#ifndef STACK_DIRECTION
|
||||
# define STACK_DIRECTION 0 /* direction unknown */
|
||||
#endif
|
||||
|
||||
#if STACK_DIRECTION != 0
|
||||
|
||||
# define STACK_DIR STACK_DIRECTION /* known at compile-time */
|
||||
|
||||
#else /* STACK_DIRECTION == 0; need run-time code */
|
||||
|
||||
static int stack_dir; /* 1 or -1 once known */
|
||||
# define STACK_DIR stack_dir
|
||||
|
||||
#endif /* STACK_DIRECTION == 0 */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* An "alloca header" is used to:
|
||||
* (a) chain together all alloca()ed blocks;
|
||||
* (b) keep track of stack depth.
|
||||
*/
|
||||
|
||||
typedef struct hdr
|
||||
{
|
||||
struct hdr * next; /* for chaining headers */
|
||||
char * deep; /* for stack depth measure */
|
||||
mempool_t * pool; /* the memory pool */
|
||||
} header;
|
||||
|
||||
static header *last_alloca_header = NULL; /* -> last alloca header */
|
||||
static header *free_header = NULL; /* List of unused structures */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
#if STACK_DIRECTION == 0
|
||||
|
||||
static void
|
||||
find_stack_direction (void)
|
||||
|
||||
/* Find the direction of the stackgrowth and store the result (+1 or -1)
|
||||
* into the global stack_dir.
|
||||
*/
|
||||
|
||||
{
|
||||
static char *addr = NULL; /* address of first `dummy', once known */
|
||||
char dummy; /* to get stack address */
|
||||
|
||||
if (addr == NULL) /* initial call */
|
||||
{
|
||||
addr = &dummy;
|
||||
find_stack_direction (); /* recurse once */
|
||||
}
|
||||
else /* second entry */
|
||||
if (&dummy > addr)
|
||||
stack_dir = 1; /* stack grew upward */
|
||||
else
|
||||
stack_dir = -1; /* stack grew downward */
|
||||
}
|
||||
|
||||
#endif /* STACK_DIRECTION == 0 */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
pointer
|
||||
palloca (size_t size)
|
||||
|
||||
/* Allocate at least <size> bytes of memory "on the stack" and return a
|
||||
* pointer to the start of the memory block. Return NULL if running out
|
||||
* of memory.
|
||||
*
|
||||
* Allocating "on the stack" means that every allocation is associated with
|
||||
* the call depth of the allocator. Allocations of a higher call depth
|
||||
* cause the deallocation of any memory allocated on deepter call depths.
|
||||
*
|
||||
* Originally this memory was meant to be taken from the stack frame of
|
||||
* the caller, but some systems and C implementations do not allow this.
|
||||
*
|
||||
* An allocation of 0 bytes is a special case, causing the deallocation of
|
||||
* every memory block allocated so far.
|
||||
*/
|
||||
|
||||
{
|
||||
char probe; /* probes stack depth: */
|
||||
register char * depth = &probe;
|
||||
register header * hp; /* current header structure */
|
||||
|
||||
#if STACK_DIRECTION == 0
|
||||
if (STACK_DIR == 0) /* (yet)unknown growth direction */
|
||||
find_stack_direction ();
|
||||
#endif
|
||||
|
||||
/* Reclaim garbage, defined as all alloca()ed storage that
|
||||
* was allocated from deeper in the stack than currently.
|
||||
*/
|
||||
|
||||
for (hp = last_alloca_header; hp != NULL;)
|
||||
{
|
||||
if ((STACK_DIR > 0 && hp->deep > depth)
|
||||
|| (STACK_DIR < 0 && hp->deep < depth))
|
||||
{
|
||||
register header *np = hp->next;
|
||||
|
||||
mempool_reset(hp->pool); /* collect garbage */
|
||||
hp->next = free_header;
|
||||
free_header = hp;
|
||||
hp = np; /* -> next header */
|
||||
}
|
||||
else
|
||||
break; /* rest are not deeper */
|
||||
}
|
||||
|
||||
last_alloca_header = hp; /* -> last valid storage */
|
||||
|
||||
/* From here on, hp is always == last_alloca_header; the
|
||||
* use of the local however is a hint for the optimizer.
|
||||
*/
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
while (free_header != NULL)
|
||||
{
|
||||
header * this = free_header;
|
||||
free_header = free_header->next;
|
||||
if (this->pool)
|
||||
{
|
||||
mempool_delete(this->pool);
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
return NULL; /* no allocation required */
|
||||
}
|
||||
|
||||
/* Allocate a new header structure if there is non for
|
||||
* this particular stack depth. The new structure will
|
||||
* be the new bottom of the header list.
|
||||
*/
|
||||
|
||||
if (hp == NULL || hp->deep != depth)
|
||||
{
|
||||
if (free_header == NULL)
|
||||
{
|
||||
hp = malloc (sizeof (*hp));
|
||||
if (!hp) { fprintf(stderr, "alloca: failed!\n"); return NULL; }
|
||||
hp->pool = new_mempool(size_mempool(1));
|
||||
if (!hp->pool)
|
||||
{
|
||||
free(hp);
|
||||
fprintf(stderr, "alloca: failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hp = free_header;
|
||||
free_header = hp->next;
|
||||
}
|
||||
|
||||
hp->next = last_alloca_header;
|
||||
hp->deep = depth;
|
||||
last_alloca_header = hp;
|
||||
}
|
||||
|
||||
/* The actual allocation is easy: */
|
||||
return mempool_alloc(hp->pool, size);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
3209
src/array.c
Normal file
3209
src/array.c
Normal file
File diff suppressed because it is too large
Load diff
137
src/array.h
Normal file
137
src/array.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
#ifndef ARRAY_H__
|
||||
#define ARRAY_H__ 1
|
||||
|
||||
#include "driver.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "svalue.h"
|
||||
|
||||
/* --- Macros --- */
|
||||
|
||||
/* vector_t *ref_array(vector_t *a)
|
||||
* Add another ref to array <a> and return the vector <a>.
|
||||
*/
|
||||
|
||||
#define ref_array(a) ((a)->ref++, (a))
|
||||
|
||||
/* void free_array(vector_t *a)
|
||||
* Subtract one ref from array <a>, and free the array fully if
|
||||
* the refcount reaches zero.
|
||||
*/
|
||||
|
||||
#define free_array(a) MACRO( if (--((a)->ref) <= 0) _free_vector(a); )
|
||||
|
||||
/* p_int deref_array(vector_t *a)
|
||||
* Subtract one ref from array <a>, but don't check if it needs to
|
||||
* be freed. Result is the number of refs left.
|
||||
*/
|
||||
|
||||
#define deref_array(a) (--(a)->ref)
|
||||
|
||||
/* See array.c for a description of what the following macros do. */
|
||||
|
||||
/* Helper for LOCAL_VECn() */
|
||||
#ifdef DEBUG
|
||||
# define VEC_DEBUGREF(ref) ref,
|
||||
#else
|
||||
# define VEC_DEBUGREF(ref)
|
||||
#endif
|
||||
#include "svalue.h"
|
||||
|
||||
#define VEC_HEAD(size) size, 1, VEC_DEBUGREF(1) NULL
|
||||
|
||||
#define VEC_SIZE(v) ((v)->size)
|
||||
|
||||
#define LOCAL_VEC1(name, type1) \
|
||||
struct { vector_t v; } name \
|
||||
= { { VEC_HEAD(1), { { type1, { 0 } } } } }
|
||||
|
||||
#define LOCAL_VEC2(name, type1, type2) \
|
||||
struct { vector_t v; svalue_t item[1]; } name \
|
||||
= { { VEC_HEAD(2), { { type1, { 0 } } } }, { { type2, { 0 } } } }
|
||||
|
||||
/* --- Types --- */
|
||||
|
||||
/* --- struct vector: the array datatype ---
|
||||
*
|
||||
* When smalloc is used, the number of elements can be deduced from
|
||||
* the memory block size, so the .size entry is not needed.
|
||||
*/
|
||||
|
||||
struct vector_s {
|
||||
p_int size; /* Number of contained elements */
|
||||
p_int ref; /* Number of references */
|
||||
#ifdef DEBUG
|
||||
p_int extra_ref; /* Second refcount, used to check .ref. */
|
||||
#endif
|
||||
wiz_list_t *user; /* Save who made the vector */
|
||||
svalue_t item[1];
|
||||
};
|
||||
|
||||
|
||||
/* --- Variables --- */
|
||||
|
||||
extern vector_t null_vector;
|
||||
|
||||
extern int num_arrays;
|
||||
extern void (*allocate_array_error_handler) (const char *, ...);
|
||||
|
||||
/* --- Prototypes --- */
|
||||
|
||||
#if defined(MALLOC_TRACE)
|
||||
|
||||
#define allocate_array(n) (_allocate_array(n, __FILE__ "::allocate_array", __LINE__))
|
||||
#define allocate_array_unlimited(n) (_allocate_array_unlimited(n, __FILE__ "::allocate_array", __LINE__))
|
||||
#define allocate_uninit_array(n) (_allocate_array(n, __FILE__ "::allocate_uninit_array", __LINE__))
|
||||
#define implode_string(a,d) (arr_implode_string(a,d, __FILE__ "::implode_string", __LINE__))
|
||||
|
||||
#else
|
||||
|
||||
#define allocate_array(n) _allocate_array(n)
|
||||
#define allocate_array_unlimited(n) _allocate_array_unlimited(n)
|
||||
#define allocate_uninit_array(n) _allocate_array(n)
|
||||
#define implode_string(a,d) arr_implode_string(a,d)
|
||||
|
||||
#endif /* MALLOC_TRACE */
|
||||
|
||||
extern vector_t *_allocate_array(mp_int MTRACE_DECL);
|
||||
extern vector_t *_allocate_array_unlimited(mp_int MTRACE_DECL);
|
||||
extern vector_t *_allocate_uninit_array(mp_int MTRACE_DECL);
|
||||
extern void _free_vector(vector_t *p);
|
||||
extern void free_empty_vector(vector_t *p);
|
||||
extern void check_for_destr(vector_t *v);
|
||||
extern string_t *arr_implode_string(vector_t *, string_t * MTRACE_DECL);
|
||||
extern vector_t *explode_string(string_t *str, string_t *del);
|
||||
extern vector_t *slice_array(vector_t *p, mp_int from, mp_int to);
|
||||
extern vector_t *add_array(vector_t *p, vector_t *q);
|
||||
extern ptrdiff_t *get_array_order (vector_t * vec );
|
||||
extern vector_t *order_array (vector_t *vec);
|
||||
extern long lookup_key (svalue_t *key, vector_t *vec);
|
||||
extern vector_t *subtract_array(vector_t *minuend, vector_t *subtrahend);
|
||||
extern Bool is_ordered(vector_t *v);
|
||||
extern vector_t *intersect_array(vector_t *vec1, vector_t *vec2);
|
||||
extern vector_t *join_array(vector_t *vec1, vector_t *vec2);
|
||||
extern vector_t * symmetric_diff_array (vector_t *vec1, vector_t *vec2);
|
||||
|
||||
extern svalue_t *v_allocate(svalue_t *sp, int num_arg);
|
||||
extern svalue_t *x_filter_array(svalue_t *sp, int num_arg);
|
||||
extern svalue_t *v_sort_array(svalue_t *sp, int num_arg);
|
||||
extern svalue_t *x_map_array(svalue_t *sp, int num_arg);
|
||||
extern svalue_t *f_transpose_array(svalue_t *sp);
|
||||
|
||||
extern svalue_t *v_filter_objects(svalue_t *sp, int num_arg);
|
||||
extern svalue_t *v_map_objects(svalue_t *sp, int num_arg);
|
||||
extern svalue_t *v_unique_array(svalue_t *sp, int num_arg);
|
||||
|
||||
extern void set_vector_user(vector_t *p, object_t *owner);
|
||||
extern long total_array_size(void);
|
||||
|
||||
extern vector_t * shrink_array (vector_t *p, mp_int n);
|
||||
|
||||
#if defined(GC_SUPPORT)
|
||||
extern void clear_array_size (void);
|
||||
extern void count_array_size (vector_t *vec);
|
||||
#endif
|
||||
|
||||
#endif /* ARRAY_H__ */
|
430
src/authlocal.c
Executable file
430
src/authlocal.c
Executable file
|
@ -0,0 +1,430 @@
|
|||
/* authlocal.c 1.0.5 - auto-authenticate users connecting from localhost.
|
||||
*
|
||||
* The procedure you want to call from your code is getUID,
|
||||
* which returns a uid_t, or 0 if authentication failed.
|
||||
* ---->> Be sure to #define USE_AUTHLOCAL if you want it to work! <<----
|
||||
*
|
||||
* Remember that uid's under 100 won't be recognized; this is because
|
||||
* they're normally system daemon accounts, not real users. If you
|
||||
* need to change this behavior, change AUTHLOCAL_MIN_UID in authlocal.h
|
||||
* before compiling.
|
||||
*
|
||||
* Copyright (C) 2002 Jeremy Monin <jeremy@shadowlands.org>
|
||||
* http://shadowlands.org/authlocal/
|
||||
* 1.0.5- 20020704.1140
|
||||
* Fixed fencepost error re matching lines on buffer boundary.
|
||||
* 1.0.4- 20020329.0140
|
||||
* Added linux 2.4 support, many descriptive comments, efficiency
|
||||
* improvements, and C-comments, not C++-comments (no //)
|
||||
* original ver. was 19990907.1515
|
||||
*/
|
||||
|
||||
#include <unistd.h> /* for ssize_t, uid_t */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for atol */
|
||||
#include <sys/types.h> /* for open */
|
||||
#include <sys/stat.h> /* for open */
|
||||
#include <fcntl.h> /* for open */
|
||||
#include <string.h> /* for memmove */
|
||||
#include <sys/socket.h> /* this is */
|
||||
#include <netinet/in.h> /* all for */
|
||||
#include <arpa/inet.h> /* inet_addr */
|
||||
|
||||
#include "authlocal.h"
|
||||
|
||||
/* -- for debug --
|
||||
|
||||
#define DEBUG_AUTHLOCAL 1
|
||||
#define USE_AUTHLOCAL 1
|
||||
char* tcpstat_fname_str = "/proc/net/tcp";
|
||||
#define TCPSTAT_FNAME tcpstat_fname_str
|
||||
|
||||
-- /for debug -- */
|
||||
|
||||
|
||||
/*
|
||||
* How it Works:
|
||||
*
|
||||
* When connecting to a TCP server from localhost, the server knows
|
||||
* the arbitrary port# you're connecting from... under linux, the file
|
||||
* /proc/net/tcp contains data about this socket, including its owner.
|
||||
* This can be used to automatically, securely authenticate.
|
||||
* See an example at the bottom of this file.
|
||||
*
|
||||
* It does lead to the problem of not _wanting_ to log in as yourself,
|
||||
* but this is a separate issue. Also, be sure root doesn't log in this way.
|
||||
* We also should check to be sure the logging-in user has a valid shell,
|
||||
* but we don't right now.
|
||||
*
|
||||
* Tested and successful under linux 2.0.x, 2.2.x, 2.4.x
|
||||
*
|
||||
* Be sure to define USE_AUTHLOCAL if you want to use this;
|
||||
* if this isn't defined, the entire getUID function will ALWAYS
|
||||
* return 0 (failure). This means you don't need to change any of
|
||||
* your other code, assuming you have a fallback method for authenticating
|
||||
* people, which you'll need anyway if you want them to be able to
|
||||
* get in from other hosts.
|
||||
*/
|
||||
|
||||
/*
|
||||
authlocal.c version 1.0.x - Automatic authentication of connections
|
||||
from localhost.
|
||||
Copyright (C) 2000-2002 Jeremy D. Monin (jeremy@shadowlands.org).
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef USE_AUTHLOCAL
|
||||
|
||||
/* yes, most of the file's in this ifdef. */
|
||||
/* Only thing that isn't is, if USE_AUTHLOCAL
|
||||
* isn't defined, the function that gets called
|
||||
* from outside this module always returns 0 (failure),
|
||||
* meaning you should fall back to standard username-and-pw-prompt
|
||||
* authentication.
|
||||
*/
|
||||
|
||||
|
||||
/* format of /proc/net/tcp lines: (as of linux v2.0-2.4, unsure in other vers)
|
||||
* We want to get the UID.
|
||||
* sl addy addy st dunno:d d:dunno uh uid timeout inode ...
|
||||
* \n n: local:port rem:port nn nnnn:nnn nn:nnnn nnn uid n n ...
|
||||
* ^^^^^^^^ ^^^^^ in hex; each is 8:4 chars
|
||||
* the ... after inode were added after 2.2.x.
|
||||
*/
|
||||
|
||||
/* PATSIZE is used in allocating buffer space AND in moving the char ptr;
|
||||
* it MUST be the correct length (incl trailing \0).
|
||||
*/
|
||||
#define PATSIZE (8+1+4+1+8+1+4+1) /* "0100007f:xxxx 0100007f:xxxx\0" */
|
||||
#define LINEBUFSIZ 4096 /* must be much bigger than line len */
|
||||
#ifndef TCPSTAT_FNAME
|
||||
#define TCPSTAT_FNAME "/proc/net/tcp"
|
||||
#endif
|
||||
|
||||
|
||||
/* check to see if we need to read more chars into the buffer;
|
||||
* if so, do that and adjust the end-of-buffer-data pointer.
|
||||
* Either way, return it. Return NULL for EOF.
|
||||
* On entry, *c points to the current buffer pos (the part we must keep).
|
||||
* (We pass **c so we can change the current buffer pos pointer in the calling
|
||||
* procedure.)
|
||||
* *c must be past the start of the buffer. (*c != buf) Otherwise how can
|
||||
* we have any room to read new data into?
|
||||
*/
|
||||
static char *read_chunk (char *buf, char **c, char *bufend, int inputfd)
|
||||
{
|
||||
ssize_t nread;
|
||||
int inbufloc = *c - buf; /* how far into buffer are we? */
|
||||
|
||||
/* Must read some into the buffer, but retain partial lines (retain what's
|
||||
* between *c and *bufend)... First, move current buffer contents up so we
|
||||
* have room for more, discarding (overwriting) what's currently before *c
|
||||
* in the buffer.
|
||||
*/
|
||||
if (inbufloc > 0)
|
||||
{
|
||||
memmove (buf, *c, LINEBUFSIZ - inbufloc);
|
||||
*c = buf + (LINEBUFSIZ - inbufloc);
|
||||
/* *c now points right after the end of the current content;
|
||||
* but in some cases this will be null-terminated, so we need to
|
||||
* not retain any \0's in the current content.
|
||||
*/
|
||||
--(*c);
|
||||
while (( *c > buf ) && (**c == '\0'))
|
||||
--(*c);
|
||||
if (**c != '\0') ++(*c);
|
||||
/* *c now points to where new stuff should be added; null-term it.
|
||||
* we'll adjust *c again soon, but this is where we need it for now.
|
||||
*/
|
||||
**c = '\0';
|
||||
}
|
||||
|
||||
/* so add the new stuff, try to fill to end of buffer */
|
||||
nread = read (inputfd, *c, LINEBUFSIZ - (*c - buf) - 1);
|
||||
if (nread == -1) {
|
||||
#ifdef DEBUG_AUTHLOCAL
|
||||
perror ("read");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
if (nread == 0) /* EOF */
|
||||
return NULL;
|
||||
|
||||
/* adjust c to start of buf, adjust end of buf ptr and return it */
|
||||
nread += (*c - buf);
|
||||
*(buf + nread) = '\0';
|
||||
*c = buf;
|
||||
|
||||
return (buf + nread);
|
||||
}
|
||||
|
||||
|
||||
/** Begin reading from a file; return the end-of-buffer-data pointer,
|
||||
* a pointer (inside buf) to the \0 right after the end of where we read,
|
||||
* or return NULL if we can't read.
|
||||
*/
|
||||
static char *buf_begin_get(char *buf, int readfromfd)
|
||||
{
|
||||
ssize_t nread = read (readfromfd, buf, LINEBUFSIZ-1);
|
||||
if (nread == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*(buf + nread) = '\0';
|
||||
return (buf + nread);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* returns 0 if something goes wrong and it can't be found.
|
||||
* (UID 0 really shouldn't be logging in from a network anyway.)
|
||||
*/
|
||||
static uid_t getUID_impl (unsigned int /* type? */ localhost_ip,
|
||||
int /* type? */ userportno, int daemonportno,
|
||||
int inputfd)
|
||||
{
|
||||
char wantthis_in_hex[PATSIZE];
|
||||
char buf[LINEBUFSIZ];
|
||||
char *b;
|
||||
char *bufend;
|
||||
char *c;
|
||||
|
||||
sprintf (wantthis_in_hex, "%08X:%04X %08X:%04X",
|
||||
localhost_ip, (int) userportno, localhost_ip, (int) daemonportno);
|
||||
|
||||
# ifdef DEBUG_AUTHLOCAL
|
||||
//fprintf (stderr, "authlocal wantthis %s\n", wantthis_in_hex);
|
||||
# endif
|
||||
|
||||
/* search for a line containing this */
|
||||
bufend = buf_begin_get (buf, inputfd);
|
||||
if (bufend == NULL) {
|
||||
return (uid_t) 0; /* couldn't read */
|
||||
}
|
||||
|
||||
/* we have c point at our current place in the buffer we search;
|
||||
* as we read more, read_chunk will adjust c as the buffer moves.
|
||||
*/
|
||||
for ( c = buf;
|
||||
(bufend != NULL) && (*c != '\0') && (c < bufend);
|
||||
bufend = read_chunk (buf, &c, bufend, inputfd))
|
||||
{
|
||||
/* remember our place, in case c is about to become NULL */
|
||||
b = c;
|
||||
# ifdef DEBUG_AUTHLOCAL
|
||||
// fprintf (stderr, "chunk is »%s«\n", b);
|
||||
# endif
|
||||
/* try to get c to point to the string we seek */
|
||||
c = strstr (c, wantthis_in_hex);
|
||||
|
||||
if (c != NULL)
|
||||
{
|
||||
/* Found a match to our pattern.
|
||||
* Now get uid and return it; we must skip ahead from where we
|
||||
* found our src/dest port pair; to go from the end of our match
|
||||
* to uid, we find and skip 5 blank areas (incl the one immediately
|
||||
* after end of match).
|
||||
* If we run out of string (find \0) before then, we have a match on
|
||||
* a partial line and need to read more of the file into the buffer.
|
||||
*/
|
||||
int bkfld;
|
||||
|
||||
/* point c at end of pattern */
|
||||
c += (PATSIZE - 1);
|
||||
|
||||
# ifdef DEBUG_AUTHLOCAL
|
||||
fprintf (stderr, "authlocal found %s\n", wantthis_in_hex);
|
||||
# endif
|
||||
|
||||
/* we're now at white space. We must skip 5 whitespace areas, and
|
||||
* the 4 fields (non-whitespace) between them. Right after the 5th
|
||||
* whitespace area is the uid field. We skip over that too, because
|
||||
* we want to null-terminate that and then go back to its start.
|
||||
*/
|
||||
for (bkfld = 1; bkfld <= 5; ++bkfld)
|
||||
{
|
||||
/* inch c forward through whitespace */
|
||||
while (*c <= ' ')
|
||||
{
|
||||
if (*c == '\0')
|
||||
{
|
||||
/* we're on a partial line, must read more file into
|
||||
* the buffer and then retry the search.
|
||||
*/
|
||||
c = NULL;
|
||||
break;
|
||||
}
|
||||
++c;
|
||||
}
|
||||
if (c == NULL) break;
|
||||
|
||||
/* now inch c forward through non-whitespace */
|
||||
while (*c > ' ')
|
||||
++c;
|
||||
}
|
||||
|
||||
if (c != NULL)
|
||||
{
|
||||
/* we're now right after end of UID; null-terminate it and move back */
|
||||
*c = '\0'; --c;
|
||||
|
||||
/* this is the field data; inch backward to next whitespace */
|
||||
while (*c > ' ')
|
||||
--c;
|
||||
|
||||
/* now nudge forward and read it! have a nice day,
|
||||
* we're done.
|
||||
*/
|
||||
++c;
|
||||
/* read it */
|
||||
return (uid_t) atol(c); /* <-------- return the uid ------ */
|
||||
|
||||
} /* end if c-not-null (partial line after match) */
|
||||
} /* end if c-not-null (no match at all) */
|
||||
|
||||
/* not found, grab more (to search through) from file into buffer, but
|
||||
* we must retain the entire last line or two of the current buffer, in
|
||||
* case we have just part of that line right now, and it's the right line
|
||||
* but we don't know it because we don't have the entire line.
|
||||
*/
|
||||
c = bufend - 1;
|
||||
/* find start of final line: */
|
||||
while ((*c != '\n') && (c != buf))
|
||||
--c;
|
||||
if ((c == buf) && (*c != '\n'))
|
||||
{
|
||||
/* found no \n in the whole buffer; a very long line.
|
||||
* the line must go away to make room. (not likely to happen)
|
||||
*/
|
||||
c = bufend;
|
||||
} else {
|
||||
char *lastlinec = c; /* remember start of final line */
|
||||
/* find start of next-to-final line: */
|
||||
while ((*c != '\n') && (c != buf))
|
||||
--c;
|
||||
if ((c == buf) && (*c != '\n'))
|
||||
c = lastlinec; /* can't keep all of the 2 lines: keep 1 */
|
||||
}
|
||||
|
||||
} /* end while-not-eof loop */
|
||||
|
||||
return (uid_t) 0; /* <-------- couldn't find it. ---------- */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* the big IFDEF */
|
||||
|
||||
|
||||
|
||||
/* Finally, here's what we need!
|
||||
* Returns 0 if something goes wrong and it can't be found.
|
||||
* (UID 0 really shouldn't be logging in from a network anyway.)
|
||||
*/
|
||||
uid_t getUID (unsigned int localhost_ip,
|
||||
int userport, int daemonport)
|
||||
{
|
||||
|
||||
#ifndef USE_AUTHLOCAL
|
||||
# ifdef DEBUG_AUTHLOCAL
|
||||
fprintf (stderr, "authlocal disabled\n");
|
||||
# endif
|
||||
return (uid_t) 0;
|
||||
#else
|
||||
uid_t retval;
|
||||
|
||||
int fd = open(TCPSTAT_FNAME, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
#ifdef DEBUG_AUTHLOCAL
|
||||
fprintf (stderr, "authlocal could not open " TCPSTAT_FNAME "\n");
|
||||
#endif
|
||||
return (uid_t) 0;
|
||||
}
|
||||
retval = getUID_impl (localhost_ip, userport, daemonport, fd);
|
||||
# ifdef DEBUG_AUTHLOCAL
|
||||
fprintf (stderr, "authlocal got uid %d for connection from %d on %d\n",
|
||||
retval, userport, daemonport);
|
||||
# endif
|
||||
close (fd);
|
||||
|
||||
if (retval > AUTHLOCAL_MIN_UID)
|
||||
return retval;
|
||||
else
|
||||
return 0;
|
||||
|
||||
#endif /* ifdef (USE_AUTHLOCAL) */
|
||||
}
|
||||
|
||||
|
||||
/* code for usage demonstration purposes. Note that it's commented out.
|
||||
|
||||
static struct in_addr localhost_ip;
|
||||
localhost_ip.s_addr = htonl(0x7f000001);
|
||||
...
|
||||
struct sockaddr_in user_address;
|
||||
int user_fd = accept
|
||||
( server_fd, (sockaddr *)&user_address, &len );
|
||||
...
|
||||
uid_t authenticated = 0;
|
||||
if (user_address.sin_addr.s_addr == localhost_ip.s_addr ) {
|
||||
|
||||
Auto-Authenticate user if logging in from localhost!
|
||||
|
||||
authenticated = getUID
|
||||
( localhost_ip.s_addr, ntohs(user_address.sin_port),
|
||||
server_portnum );
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int pnum_cli = 2048;
|
||||
int pnum_srv = 5000;
|
||||
int retuid;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
if (strncasecmp(argv[1], "0x", 2))
|
||||
pnum_cli = (int) strtol(argv[1], (char **)NULL, 10);
|
||||
else
|
||||
pnum_cli = (int) strtol(argv[1], (char **)NULL, 16);
|
||||
}
|
||||
if (argc > 2)
|
||||
{
|
||||
if (strncasecmp(argv[2], "0x", 2))
|
||||
pnum_srv = (int) strtol(argv[2], (char **)NULL, 10);
|
||||
else
|
||||
pnum_srv = (int) strtol(argv[2], (char **)NULL, 16);
|
||||
}
|
||||
#ifdef DEBUG_AUTHLOCAL
|
||||
if (argc > 3)
|
||||
tcpstat_fname_str = argv[3];
|
||||
printf ("file for /proc/net/tcp is %s\n", tcpstat_fname_str);
|
||||
#endif
|
||||
|
||||
printf ("lookin' for a connection from port %d (0x%04X) to %d (0x%04X)\n",
|
||||
pnum_cli, pnum_cli, pnum_srv, pnum_srv);
|
||||
retuid = (int) getUID ( inet_addr ("127.0.0.1"), pnum_cli, pnum_srv);
|
||||
printf ("returned %d\n", retuid);
|
||||
|
||||
return (retuid ? 0 : 1);
|
||||
}
|
||||
|
||||
|
||||
authlocal.c ENDS. */
|
48
src/authlocal.h
Executable file
48
src/authlocal.h
Executable file
|
@ -0,0 +1,48 @@
|
|||
/* authlocal.h - auto-authenticate users connecting from localhost.
|
||||
|
||||
The procedure you want to call from your code is getUID,
|
||||
which returns a uid_t, or 0 if authentication failed.
|
||||
Be sure to #define USE_AUTHLOCAL if you want it to work!
|
||||
|
||||
Copyright (C) 1999-2002 Jeremy D. Monin (jeremy@shadowlands.org).
|
||||
http://shadowlands.org/authlocal/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _AUTHLOCAL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Below this minimum UID, no users will be authenticated.
|
||||
* (these are usually system pseudouser accounts.)
|
||||
*/
|
||||
#define AUTHLOCAL_MIN_UID 100
|
||||
|
||||
uid_t getUID (unsigned int localhost_ip,
|
||||
int userport, int daemonport);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define _AUTHLOCAL_H_
|
||||
#endif
|
||||
|
7
src/autoconf/Makefile
Normal file
7
src/autoconf/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
../configure: configure.in configure.head Makefile
|
||||
autoconf
|
||||
rm -f $@
|
||||
cat configure.head configure >>$@
|
||||
chmod +x $@
|
||||
@rm configure
|
||||
|
138
src/autoconf/acconfig.h
Normal file
138
src/autoconf/acconfig.h
Normal file
|
@ -0,0 +1,138 @@
|
|||
#ifndef MACHINE_H
|
||||
#define MACHINE_H
|
||||
|
||||
@TOP@
|
||||
|
||||
/* Set in response to the signal handler return type, since not all
|
||||
* compilers understand direct definition comparisons
|
||||
*/
|
||||
#undef RETSIGTYPE_VOID
|
||||
|
||||
/* does the compiler provide inline functions? */
|
||||
#undef HAS_INLINE
|
||||
|
||||
/* Is the library function inet_ntoa() compatible with the compiler?
|
||||
* TODO: Is there any platform where this is not the case?
|
||||
*/
|
||||
#undef INET_NTOA_OK
|
||||
|
||||
/* A mask that allows to extract an unsigned char from a signed */
|
||||
#define CHARBIT_MASK 0xff
|
||||
|
||||
#undef RENAME_HANDLES_DIRECTORIES
|
||||
|
||||
/* Does the system have a getrusage call? */
|
||||
#undef HAVE_GETRUSAGE
|
||||
/* If so, is it restricted to user and system time? */
|
||||
#undef GETRUSAGE_RESTRICTED
|
||||
/* Is it available as a subfunction of syscall() ? */
|
||||
#undef GETRUSAGE_VIA_SYSCALL
|
||||
/* Can ru_utime / ru_stime be accessed as a timeval with tv_sec and tv_usec ? */
|
||||
#undef RUSAGE_USEC
|
||||
|
||||
/* the atari strtol() used to consider characters '9' < c < 'A' to be numeric */
|
||||
#undef STRTOL_BROKEN
|
||||
|
||||
/* does the libc consider it normal to free a null pointer? */
|
||||
#undef FREE_NULL_POINTER
|
||||
|
||||
/* needs the first argument of strtol be declared as const ? */
|
||||
#undef STRTOL_CONST_CHARP
|
||||
|
||||
/* Define if you have bcopy, and it handles overlapping ranges correctly. */
|
||||
#undef OVERLAPPING_BCOPY
|
||||
|
||||
#define MALLOC_ALIGN 4
|
||||
|
||||
/* does the sys/types.h define the uint*_t types? */
|
||||
#undef HAVE_INTTYPES
|
||||
|
||||
/* does the compiler know of a 'ssize_t' type? */
|
||||
#undef HAVE_SSIZE_T
|
||||
|
||||
/* does the compiler know of a 'long long' type? */
|
||||
#undef HAVE_LONG_LONG
|
||||
|
||||
/* does the compiler know of a 'bool' type? */
|
||||
#undef HAVE_BOOL
|
||||
|
||||
/* what kind of pointer is used by malloc() et al */
|
||||
#define POINTER *
|
||||
#undef FREE_RETURNS_VOID
|
||||
|
||||
/* can we define our own malloc() safely? */
|
||||
#undef SBRK_OK
|
||||
|
||||
/* The following is needed for smalloc without SBRK_OK to use memory
|
||||
* efficiently. smalloc will malloc blocks that are a large power of
|
||||
* two, minus EXTERN_MALLOC_OVERHEAD. If you have no idea what number to
|
||||
* choose, compile & run util/overhead.c
|
||||
*/
|
||||
#define EXTERN_MALLOC_OVERHEAD 16
|
||||
|
||||
/* How to set a socket non-blocking */
|
||||
#undef USE_IOCTL_FIONBIO
|
||||
#undef USE_FCNTL_O_NDELAY
|
||||
#undef USE_FCNTL_FNDELAY
|
||||
|
||||
/* Can F_SETOWN be used on a socket? */
|
||||
#undef USE_FCNTL_SETOWN
|
||||
|
||||
/* Can SO_OOBINLINE be used on a socket? */
|
||||
#undef USE_OOBINLINE
|
||||
|
||||
/* Does the machine offer IPv6? */
|
||||
#undef HAS_IPV6
|
||||
|
||||
/* Does the machine offer iconv? */
|
||||
#undef HAS_ICONV
|
||||
|
||||
/* Does the machine's iconv take a non-const 'char**' as first arg? */
|
||||
#undef HAS_ICONV_NONCONST_IN
|
||||
|
||||
/* Does the machine offer PCRE? */
|
||||
#undef HAS_PCRE
|
||||
|
||||
/* Does the machine offer IDNA? */
|
||||
#undef HAS_IDN
|
||||
|
||||
/* Does the machine offer mySQL? */
|
||||
#undef HAS_MYSQL
|
||||
|
||||
/* Does the machine offer PostgreSQL? */
|
||||
#undef HAS_PGSQL
|
||||
|
||||
/* Does the machine offer SQLite3? */
|
||||
#undef HAS_SQLITE3
|
||||
|
||||
/* Does SQLite3 use pthreads? */
|
||||
#undef SQLITE3_USES_PTHREADS
|
||||
|
||||
/* Does the machine offer JSON (json-c)? */
|
||||
#undef HAS_JSON
|
||||
|
||||
/* Does the machine offer expat? */
|
||||
#undef HAS_EXPAT
|
||||
|
||||
/* Does the machine offer GnuTLS? */
|
||||
#undef HAS_GNUTLS
|
||||
#undef HAS_GNUTLS_VERSION
|
||||
|
||||
/* Does the machine offer OpenSSL/SSL? */
|
||||
#undef HAS_OPENSSL
|
||||
|
||||
/* define the erq include file. */
|
||||
#undef ERQ_INCLUDE
|
||||
|
||||
/* Does the machine offer pthreads? */
|
||||
#undef HAS_PTHREADS
|
||||
|
||||
/* Does the machine offer pthread_atfork()? */
|
||||
#undef HAS_PTHREAD_ATFORK
|
||||
|
||||
/* define the host-specific include file */
|
||||
#undef HOST_INCLUDE
|
||||
|
||||
@BOTTOM@
|
||||
|
||||
#endif
|
12
src/autoconf/configure.head
Normal file
12
src/autoconf/configure.head
Normal file
|
@ -0,0 +1,12 @@
|
|||
#! /bin/sh
|
||||
##
|
||||
## never edit ./configure manually, it is being generated by autoconf.
|
||||
##
|
||||
## this special prefix prepended by autoconf/Makefile --lynX
|
||||
|
||||
if test "x$*" = "x"; then
|
||||
echo "Restarting: configure --with-setting psyced"
|
||||
settings/psyced
|
||||
exit
|
||||
fi
|
||||
|
2894
src/autoconf/configure.in
Normal file
2894
src/autoconf/configure.in
Normal file
File diff suppressed because it is too large
Load diff
1552
src/backend.c
Normal file
1552
src/backend.c
Normal file
File diff suppressed because it is too large
Load diff
63
src/backend.h
Normal file
63
src/backend.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
#ifndef BACKEND_H__
|
||||
#define BACKEND_H__ 1
|
||||
|
||||
#include "driver.h"
|
||||
#include "typedefs.h"
|
||||
#include "main.h" /* max_time */
|
||||
|
||||
/* --- Types --- */
|
||||
|
||||
/* struct statistic_s: Aggregate data for statistics.
|
||||
*
|
||||
* In particular the structures is used with update_statistic() in order
|
||||
* to calculate a weighted average of the last period of time.
|
||||
*/
|
||||
|
||||
struct statistic_s
|
||||
{
|
||||
mp_int last_time; /* Time of last weighted-average calculation. */
|
||||
long sum; /* Sum since last weighted-average calculation. */
|
||||
double weighted_avg; /* The current weighted average. */
|
||||
};
|
||||
|
||||
/* --- Variables --- */
|
||||
|
||||
extern mp_int current_time;
|
||||
extern Bool time_to_call_heart_beat;
|
||||
extern volatile Bool comm_time_to_call_heart_beat;
|
||||
extern uint32 total_player_commands;
|
||||
extern volatile mp_int total_alarms;
|
||||
extern uint num_listed_objs;
|
||||
extern uint num_last_processed;
|
||||
extern uint num_last_data_cleaned;
|
||||
extern statistic_t stat_last_processed;
|
||||
extern statistic_t stat_last_data_cleaned;
|
||||
extern statistic_t stat_in_list;
|
||||
|
||||
extern Bool extra_jobs_to_do;
|
||||
|
||||
typedef enum { gcDont = 0, gcMalloc, gcEfun } GC_Request;
|
||||
extern GC_Request gc_request;
|
||||
extern statistic_t stat_load;
|
||||
extern statistic_t stat_compile;
|
||||
|
||||
extern Bool mud_is_up;
|
||||
|
||||
/* --- Prototypes --- */
|
||||
|
||||
extern void clear_state (void);
|
||||
extern void check_alarm (void);
|
||||
extern void backend (void);
|
||||
extern void preload_objects (int eflag);
|
||||
extern svalue_t *f_debug_message (svalue_t *sp);
|
||||
ALARM_HANDLER_PROT(catch_alarm);
|
||||
extern void update_statistic (statistic_t * pStat, long number);
|
||||
extern void update_statistic_avg (statistic_t * pStat, long number);
|
||||
extern double relate_statistics (statistic_t sStat, statistic_t sRef);
|
||||
extern void update_compile_av (int lines);
|
||||
extern svalue_t *v_garbage_collection(svalue_t *sp, int num_arg);
|
||||
extern svalue_t *f_query_load_average(svalue_t *sp);
|
||||
|
||||
/* --- Macros --- */
|
||||
|
||||
#endif /* BACKEND_H__ */
|
1073
src/bitstrings.c
Normal file
1073
src/bitstrings.c
Normal file
File diff suppressed because it is too large
Load diff
24
src/bitstrings.h
Normal file
24
src/bitstrings.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef BITSTRINGS_H__
|
||||
#define BITSTRINGS_H__ 1
|
||||
|
||||
#include "driver.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
/* --- Variables --- */
|
||||
|
||||
/* --- Prototypes --- */
|
||||
|
||||
extern svalue_t *f_clear_bit (svalue_t *sp);
|
||||
extern svalue_t *f_set_bit(svalue_t *);
|
||||
extern svalue_t *f_test_bit(svalue_t *);
|
||||
extern svalue_t *f_or_bits(svalue_t *);
|
||||
extern svalue_t *f_and_bits(svalue_t *);
|
||||
extern svalue_t *f_xor_bits(svalue_t *);
|
||||
extern svalue_t *f_invert_bits(svalue_t *);
|
||||
extern svalue_t *f_last_bit(svalue_t *);
|
||||
extern svalue_t *f_next_bit(svalue_t *);
|
||||
extern svalue_t *f_count_bits(svalue_t *);
|
||||
extern svalue_t *v_copy_bits(svalue_t *, int num_arg);
|
||||
|
||||
#endif /* BITSTRINGS_H__ */
|
||||
|
291
src/bytecode.h
Normal file
291
src/bytecode.h
Normal file
|
@ -0,0 +1,291 @@
|
|||
#ifndef BYTECODE_H__
|
||||
#define BYTECODE_H__ 1
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Types and Macros used to describe bytecode
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
* While topically part of exec.h, the actual bytecode types and macros
|
||||
* have been exported into this file to reduce the coupling on exec.h.
|
||||
* Most files only need to know about bytecode_t and bytecode_p, and not
|
||||
* about all the other stuff in exec.h .
|
||||
*
|
||||
* Bytecode
|
||||
* --------
|
||||
*
|
||||
* As the name conveys, the LPC programs are compiled into a bytecode,
|
||||
* assuming 8-Bit-Bytes. Since we have more than 256 opcodes, the less
|
||||
* often used instructions are encoded in two-byte opcodes: a prefix
|
||||
* byte and an sub-opcode. The translation opcode -> prefix:sub-opcode
|
||||
* is defined in the instrs[] table using the .prefix and .opcode
|
||||
* fields.
|
||||
*
|
||||
* To achieve platform independance, the driver does not operate directly
|
||||
* with 'char's and 'char *'s, but instead with 'bytecode_t' and
|
||||
* 'bytecode_p's. Combined with some macros this allows the implementation
|
||||
* even on platforms with CHAR_BITs != 8.
|
||||
* TODO: This support is far from complete/comprehensive, and some values
|
||||
* TODO:: in the bytecode are stored in host-sizes and -layouts.
|
||||
*
|
||||
* The bytecode itself is divided into functions: the code for every
|
||||
* function is (except for absolute jumps) selfcontained and prepended
|
||||
* by a header holding the name of the function, and the number and types
|
||||
* of expected arguments. The advantage is that for a given function
|
||||
* the driver does not need to know if it is part of a program or a
|
||||
* lambda closure compiled at runtime: in both cases all necessary
|
||||
* information about the function is right where its code is.
|
||||
*
|
||||
* The maximum size of a program is limited by the biggest offset
|
||||
* that can be stored in the 'functions' array, currently 1 MByte.
|
||||
* A lot of internal offset counters are shorts even, though so far
|
||||
* this never caused a problem.
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "driver.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
|
||||
/* --- Byte code ---
|
||||
*
|
||||
* The program code is stored as byte code. The following definitions
|
||||
* and macros allow its implementation even on platforms with more than
|
||||
* 8 bits per character.
|
||||
* TODO: This portability is far from complete, and not used everywhere,
|
||||
* TODO:: not even in the compiler.
|
||||
*
|
||||
* bytecode_t: an integral type holding the numbers 0..255.
|
||||
* bytecode_p: an integral type addressing a bytecode. This need not
|
||||
* be a pointer.
|
||||
*
|
||||
* bytecode_t GET_CODE(bytecode_p p)
|
||||
* bytecode_t LOAD_CODE(bytecode_p p)
|
||||
* Return the bytecode from *p, the LOAD_ variant then increments p.
|
||||
*
|
||||
* void PUT_CODE(bytecode_p p, bytecode_t c)
|
||||
* void STORE_CODE(bytecode_p p, bytecode_t c)
|
||||
* void RSTORE_CODE(bytecode_p p, bytecode_t c)
|
||||
* Store the bytecode c in *p, the STORE_ variant then increments p.
|
||||
* The RSTORE_ variant pre-decrements p.
|
||||
*
|
||||
* char GET_INT8(p) , LOAD_INT8(p)
|
||||
* uchar GET_UINT8(p), LOAD_UINT8(p)
|
||||
* Return the 8-Bit (unsigned) int stored at <p>, the LOAD_ variants
|
||||
* then increment <p>.
|
||||
*
|
||||
* void PUT_INT8(p, char c), STORE_INT8(p, char c)
|
||||
* void PUT_UINT8(p, uchar c), STORE_UINT8(p, uchar c)
|
||||
* Store the 8-Bit (unsigned) int <c> into <p>, the STORE_ variants
|
||||
* then increment <p>.
|
||||
*
|
||||
* void GET_SHORT ([unsigned] short d, bytecode_p p)
|
||||
* void LOAD_SHORT([unsigned] short d, bytecode_p p)
|
||||
* Load the (unsigned) short 'd' stored at <p>, the LOAD_ variant
|
||||
* then increments <p>.
|
||||
* TODO: Currently, all SHORTs must be 2 bytes.
|
||||
*
|
||||
* void PUT_SHORT (bytecode_p p, [unsigned] short d)
|
||||
* void STORE_SHORT(bytecode_p p, [unsigned] short d)
|
||||
* void RSTORE_SHORT(bytecode_p p, [unsigned] short d)
|
||||
* Store the (unsigned) short <d> into <p>, the STORE_ variant
|
||||
* then increments <p>. The RSTORE_ variant pre-decrements <p>.
|
||||
* TODO: Currently, all SHORTs must be 2 bytes.
|
||||
*
|
||||
* void GET_INT16 ([unsigned] int16 d, bytecode_p p)
|
||||
* void LOAD_INT16([unsigned] int16 d, bytecode_p p)
|
||||
* Load the (unsigned) int16 'd' stored at <p>, the LOAD_ variant
|
||||
* then increments <p>.
|
||||
*
|
||||
* void GET_LONG ([unsigned] long d, bytecode_p p)
|
||||
* void LOAD_LONG([unsigned] long d, bytecode_p p)
|
||||
* Load the (unsigned) long 'd' stored at <p>, the LOAD_ variant
|
||||
* then increments <p>.
|
||||
* TODO: Currently, all LONGs must be 4 bytes.
|
||||
*
|
||||
* void PUT_LONG (bytecode_p p, [unsigned] long d)
|
||||
* void STORE_LONG(bytecode_p p, [unsigned] long d)
|
||||
* void RSTORE_LONG(bytecode_p p, [unsigned] long d)
|
||||
* Store the (unsigned) long <d> into <p>, the STORE_ variant
|
||||
* then increments <p>. The RSTORE_ variant pre-decrements <p>.
|
||||
* TODO: Currently, all LONGs must be 4 bytes.
|
||||
*
|
||||
* void LOAD_INT32([unsigned] int32 d, bytecode_p p)
|
||||
* void GET_INT32([unsigned] int32 d, bytecode_p p)
|
||||
* Load the (unsigned) in32 'd' stored at <p>, the LOAD_ variant
|
||||
* then increments <p>.
|
||||
*
|
||||
* void STORE_INT32([unsigned] int32 d, bytecode_p p)
|
||||
* void PUT_INT32([unsigned] int32 d, bytecode_p p)
|
||||
* Store the (unsigned) int32 'd' at <p>, the STORE_ variant
|
||||
* then increments <p>.
|
||||
*/
|
||||
|
||||
#if CHAR_BIT == 8
|
||||
typedef unsigned char bytecode_t;
|
||||
typedef bytecode_t * bytecode_p;
|
||||
|
||||
#define GET_CODE(p) (*(p))
|
||||
#define LOAD_CODE(p) (*(p)++)
|
||||
|
||||
#define PUT_CODE(p,c) (*(p) = (c))
|
||||
#define STORE_CODE(p,c) (*(p)++ = (c))
|
||||
#define RSTORE_CODE(p,c) (*--(p) = (c))
|
||||
|
||||
/* TODO: all these casts yield rvalues, so they shouldn't compile
|
||||
* TODO:: (and on xlc on AIX some of them indeed don't).
|
||||
*/
|
||||
#define GET_UINT8(p) (*((unsigned char *)(p)))
|
||||
#define GET_INT8(p) (*((signed char *)(p)))
|
||||
#define LOAD_UINT8(p) (*((unsigned char *)(p)++))
|
||||
#define LOAD_INT8(p) (*((signed char *)(p)++))
|
||||
|
||||
#define PUT_UINT8(p,c) (*((unsigned char *)(p)) = (c))
|
||||
#define PUT_INT8(p,c) (*((signed char *)(p)) = (c))
|
||||
#define STORE_UINT8(p,c) (*((unsigned char *)(p)++) = (c))
|
||||
#define STORE_INT8(p,c) (*((signed char *)(p)++) = (c))
|
||||
|
||||
/* TODO: These generic mem-macros should go into a macros.h. See also
|
||||
* TODO:: how mudos does it.
|
||||
* Note: the lowlevel BYTE macros can't use MACRO(), since this is
|
||||
* needed on the next abstraction level, and a macro can't be nested
|
||||
* into itself.
|
||||
*/
|
||||
#define LOAD_2BYTE(d,p) ( ((char *)&(d))[0] = *(char *)(p)++, \
|
||||
((char *)&(d))[1] = *(char *)(p)++)
|
||||
|
||||
#define GET_2BYTE(d,p) ( ((char *)&(d))[0] = ((char *)(p))[0], \
|
||||
((char *)&(d))[1] = ((char *)(p))[1] )
|
||||
|
||||
#define STORE_2BYTE(p,d) do {\
|
||||
unsigned char * _q, ** _qq; \
|
||||
_q = (unsigned char *)(p); \
|
||||
_qq = (unsigned char **)&(p); \
|
||||
_q[0] = ((unsigned char *)&(d))[0]; \
|
||||
_q[1] = ((unsigned char *)&(d))[1]; \
|
||||
*_qq += 2; \
|
||||
} while(0)
|
||||
|
||||
#define RSTORE_2BYTE(p,d) do {\
|
||||
unsigned char * _q, ** _qq; \
|
||||
_q = (unsigned char *)(p); \
|
||||
_qq = (unsigned char **)&(p); \
|
||||
_q[-2] = ((unsigned char *)&(d))[0]; \
|
||||
_q[-1] = ((unsigned char *)&(d))[1]; \
|
||||
*_qq -= 2; \
|
||||
} while(0)
|
||||
|
||||
#define PUT_2BYTE(p,d) ( ((char *)(p))[0] = ((char *)&(d))[0], \
|
||||
((char *)(p))[1] = ((char *)&(d))[1] )
|
||||
|
||||
#define LOAD_3BYTE(d,p) ( (d) = ((*(unsigned char *)(p)++) << 16) \
|
||||
| ((*(unsigned char *)(p)++) << 8) \
|
||||
| (*(unsigned char *)(p)++) )
|
||||
|
||||
#define GET_3BYTE(d,p) ( (d) = ((((unsigned char *)(p))[0]) << 16) \
|
||||
| ((((unsigned char *)(p))[1]) << 8) \
|
||||
| (((unsigned char *)(p))[2]) )
|
||||
|
||||
#define STORE_3BYTE(p,d) do {\
|
||||
unsigned char * _q, ** _qq; \
|
||||
unsigned long _d = (unsigned long)(d); \
|
||||
_q = (unsigned char *)(p); \
|
||||
_qq = (unsigned char **)&(p); \
|
||||
_q[0] = (unsigned char) (_d >> 16) \
|
||||
_q[1] = (unsigned char) (_d >> 8) \
|
||||
_q[2] = (unsigned char) (_d) \
|
||||
*_qq += 3; \
|
||||
} while(0)
|
||||
|
||||
#define PUT_3BYTE(p,d) ( ((unsigned char *)(p))[0] = (unsigned char)((d) >> 16), \
|
||||
((unsigned char *)(p))[1] = (unsigned char)((d) >> 8), \
|
||||
((unsigned char *)(p))[2] = (unsigned char)(d) )
|
||||
|
||||
#define LOAD_4BYTE(d,p) ( ((char *)&(d))[0] = *(char *)(p)++, \
|
||||
((char *)&(d))[1] = *(char *)(p)++, \
|
||||
((char *)&(d))[2] = *(char *)(p)++, \
|
||||
((char *)&(d))[3] = *(char *)(p)++ )
|
||||
|
||||
#define GET_4BYTE(d,p) ( ((char *)&(d))[0] = ((char *)(p))[0], \
|
||||
((char *)&(d))[1] = ((char *)(p))[1], \
|
||||
((char *)&(d))[2] = ((char *)(p))[2], \
|
||||
((char *)&(d))[3] = ((char *)(p))[3] )
|
||||
|
||||
#define STORE_4BYTE(p,d) ( *(unsigned char *)(p)++ = ((char *)&(d))[0], \
|
||||
*(unsigned char *)(p)++ = ((char *)&(d))[1], \
|
||||
*(unsigned char *)(p)++ = ((char *)&(d))[2], \
|
||||
*(unsigned char *)(p)++ = ((char *)&(d))[3] )
|
||||
|
||||
#define PUT_4BYTE(p,d) ( ((char *)(p))[0] = ((char *)&(d))[0], \
|
||||
((char *)(p))[1] = ((char *)&(d))[1], \
|
||||
((char *)(p))[2] = ((char *)&(d))[2], \
|
||||
((char *)(p))[3] = ((char *)&(d))[3] )
|
||||
|
||||
|
||||
#if SIZEOF_SHORT == 2
|
||||
# define GET_SHORT(d,p) GET_2BYTE(d,p)
|
||||
# define LOAD_SHORT(d,p) LOAD_2BYTE(d,p)
|
||||
# define PUT_SHORT(p,d) MACRO(unsigned short _us = (unsigned short)d; \
|
||||
PUT_2BYTE(p,_us);)
|
||||
# define STORE_SHORT(p,d) MACRO(unsigned short _us = (unsigned short)d; \
|
||||
STORE_2BYTE(p,_us);)
|
||||
# define RSTORE_SHORT(p,d) MACRO(unsigned short _us = (unsigned short)d; \
|
||||
RSTORE_2BYTE(p,_us);)
|
||||
#else
|
||||
# error "Unsupported size of short."
|
||||
#endif
|
||||
|
||||
#if SIZEOF_LONG == 4
|
||||
# define GET_LONG(d,p) GET_4BYTE(d,p)
|
||||
# define LOAD_LONG(d,p) LOAD_4BYTE(d,p)
|
||||
# define PUT_LONG(p,d) MACRO(unsigned long _us = (unsigned long)d; \
|
||||
PUT_4BYTE(p,_us);)
|
||||
# define STORE_LONG(p,d) MACRO(unsigned long _us = (unsigned long)d; \
|
||||
STORE_4BYTE(p,_us);)
|
||||
# define RSTORE_LONG(p,d) MACRO(unsigned long _us = (unsigned long)d; \
|
||||
RSTORE_4BYTE(p,_us);)
|
||||
#elif SIZEOF_LONG == 8 && SIZEOF_INT == 4
|
||||
# define GET_LONG(d,p) MACRO(int _ui; GET_4BYTE(_ui,p); \
|
||||
d = _ui;)
|
||||
# define LOAD_LONG(d,p) MACRO(int _ui; LOAD_4BYTE(_ui,p); \
|
||||
d = _ui;)
|
||||
# define PUT_LONG(p,d) MACRO(unsigned int _ui = (unsigned int)d; \
|
||||
PUT_4BYTE(p,_ui);)
|
||||
# define STORE_LONG(p,d) MACRO(unsigned int _ui = (unsigned int)d; \
|
||||
STORE_4BYTE(p,_ui);)
|
||||
# define RSTORE_LONG(p,d) MACRO(unsigned int _ui = (unsigned int)d; \
|
||||
RSTORE_4BYTE(p,_ui);)
|
||||
#else
|
||||
# error "Unsupported size of long."
|
||||
#endif
|
||||
|
||||
#define LOAD_INT16(d,p) LOAD_2BYTE(d,p)
|
||||
|
||||
#define GET_INT32(d,p) GET_4BYTE(d,p)
|
||||
#define PUT_INT32(p,d) PUT_4BYTE(p,d)
|
||||
|
||||
#ifdef NO64BIT
|
||||
# define LOAD_INT32(d,p) LOAD_4BYTE(d,p)
|
||||
# define STORE_INT32(p,d) STORE_4BYTE(p,d)
|
||||
#else
|
||||
# define GET_LONG(d,p) GET_4BYTE(d,p)
|
||||
# define LOAD_LONG(d,p) LOAD_4BYTE(d,p)
|
||||
# define PUT_LONG(p,d) MACRO(unsigned long _us = (unsigned long)d; \
|
||||
PUT_4BYTE(p,_us);)
|
||||
# define STORE_LONG(p,d) MACRO(unsigned long _us = (unsigned long)d; \
|
||||
STORE_4BYTE(p,_us);)
|
||||
# define RSTORE_LONG(p,d) MACRO(unsigned long _us = (unsigned long)d; \
|
||||
RSTORE_4BYTE(p,_us);)
|
||||
/* TODO: The above assumes sizeof(long) == 4. */
|
||||
|
||||
# define LOAD_INT32(d,p) LOAD_2BYTE(d,p)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef GET_CODE
|
||||
# error "No bytecode type defined."
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#endif /* BYTECODE_H__ */
|
847
src/call_out.c
Normal file
847
src/call_out.c
Normal file
|
@ -0,0 +1,847 @@
|
|||
/*---------------------------------------------------------------------------
|
||||
* Gamedriver Callout handling.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
* Callouts are delayed calls to (non-static) functions, with delays
|
||||
* measured in seconds. The minimal resolution is of course the duration
|
||||
* a backend cycle. The command_giver is saved over the delay.
|
||||
*
|
||||
* As a simplistic measure against 'rabbits' (think fork-bombs using
|
||||
* callouts), the callouts of one user can use only MAX_EVAL_COST at
|
||||
* one time altogether.
|
||||
*
|
||||
* Pending call outs are held in a list, sorted in ascending order of
|
||||
* remaining delaytime. The actual delay values stored are deltas: the
|
||||
* delay this callout is to be scheduled after its predecessor in
|
||||
* the list.
|
||||
*
|
||||
* TODO: It would be nice if the callout would store from where the
|
||||
* TODO:: callout originated and fake a control-stack entry for a proper
|
||||
* TODO:: traceback. However, this has to take swapping into account.
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "driver.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
#include "call_out.h"
|
||||
#include "actions.h"
|
||||
#include "array.h"
|
||||
#include "backend.h"
|
||||
#include "closure.h"
|
||||
#include "comm.h"
|
||||
#include "exec.h"
|
||||
#include "gcollect.h"
|
||||
#include "interpret.h"
|
||||
#include "main.h"
|
||||
#include "mstrings.h"
|
||||
#include "object.h"
|
||||
#include "simulate.h"
|
||||
#include "stdstrings.h"
|
||||
#include "strfuns.h"
|
||||
#include "svalue.h"
|
||||
#ifdef USE_SWAP
|
||||
#include "swap.h"
|
||||
#endif
|
||||
#include "wiz_list.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#include "../mudlib/sys/debug_info.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* The description of one callout.
|
||||
*
|
||||
* The function to call be either given by object:name or as closure.
|
||||
*/
|
||||
|
||||
struct call {
|
||||
struct call *next; /* link to next structure */
|
||||
/* TODO: p_int or mp_int */ int delta; /* Delay in relation to the previous structure */
|
||||
callback_t fun;
|
||||
object_t *command_giver; /* the saved command_giver */
|
||||
};
|
||||
|
||||
|
||||
static struct call *call_list = NULL;
|
||||
/* The list of pending call_outs, sorted in ascending order of delay.
|
||||
*/
|
||||
|
||||
static long num_callouts = 0;
|
||||
/* Number of active callouts.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static INLINE void
|
||||
free_call (struct call *cop)
|
||||
|
||||
/* Deallocate all resources bound to <cop> and put <cop> into the free list.
|
||||
* This can be used for used and unused callouts alike.
|
||||
*/
|
||||
|
||||
{
|
||||
free_callback(&(cop->fun));
|
||||
|
||||
if (cop->command_giver)
|
||||
free_object(cop->command_giver, "free_call");
|
||||
|
||||
pfree(cop);
|
||||
} /* free_call() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void
|
||||
insert_call (struct call *cop, int delay)
|
||||
|
||||
/* Inser the call_out structure <cop> with the <delay> into the callout
|
||||
* list.
|
||||
*/
|
||||
|
||||
{
|
||||
struct call **copp; /* Auxiliary pointers for list insertion */
|
||||
struct call *cop2;
|
||||
|
||||
num_callouts++;
|
||||
for (copp = &call_list; NULL != (cop2 = *copp); copp = &cop2->next)
|
||||
{
|
||||
int delta;
|
||||
if ((delta = cop2->delta) >= delay)
|
||||
{
|
||||
cop2->delta -= delay;
|
||||
cop->delta = delay;
|
||||
cop->next = *copp;
|
||||
*copp = cop;
|
||||
return;
|
||||
}
|
||||
delay -= (delta >= 0 ? delta : 0);
|
||||
/* Especially when called from within a call_out, delta may be
|
||||
* negative.
|
||||
*/
|
||||
}
|
||||
*copp = cop;
|
||||
cop->delta = delay;
|
||||
cop->next = NULL;
|
||||
} /* insert_call() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
svalue_t *
|
||||
v_call_out (svalue_t *sp, int num_arg)
|
||||
|
||||
/* EFUN: call_out()
|
||||
*
|
||||
* void call_out(string fun, int delay, mixed arg, ...)
|
||||
* void call_out(closure cl, int delay, mixed arg, ...)
|
||||
*
|
||||
* Set up a call to function fun or closure cl in the current
|
||||
* object. The call will take place in delay seconds, with the
|
||||
* remaining argument list provided. References in the argument list
|
||||
* will be passed as number 0, though.
|
||||
*/
|
||||
|
||||
{
|
||||
svalue_t *arg; /* Pointer to efun arguments */
|
||||
int delay;
|
||||
struct call *cop; /* New callout structure */
|
||||
int error_index;
|
||||
|
||||
arg = sp - num_arg + 1;
|
||||
|
||||
/* If the current object is destructed, free everything on the stack
|
||||
* and return.
|
||||
*/
|
||||
|
||||
if (current_object->flags & O_DESTRUCTED)
|
||||
{
|
||||
do {
|
||||
free_svalue(sp--);
|
||||
} while (--num_arg);
|
||||
return sp;
|
||||
}
|
||||
|
||||
if (max_callouts && max_callouts <= num_callouts)
|
||||
{
|
||||
errorf("Too many callouts at once (max. %ld).\n", (long)max_callouts);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* Get a new call structure.
|
||||
* Note: it is not useful to pool these allocations, as muds tend
|
||||
* to have spikes of high callout usage, but a low longterm average
|
||||
* usage. Any overhead savings by a pool are more than made up
|
||||
* by the unused structures sitting around.
|
||||
*/
|
||||
cop = pxalloc(sizeof (struct call));
|
||||
|
||||
/* Get the function designation from the stack */
|
||||
|
||||
if (arg[0].type == T_STRING)
|
||||
{
|
||||
error_index = setup_function_callback(&(cop->fun), current_object
|
||||
, arg[0].u.str
|
||||
, num_arg-2, arg+2
|
||||
, MY_TRUE
|
||||
);
|
||||
free_string_svalue(arg);
|
||||
}
|
||||
else
|
||||
error_index = setup_closure_callback(&(cop->fun), arg
|
||||
, num_arg-2, arg+2
|
||||
, MY_TRUE
|
||||
);
|
||||
|
||||
if (error_index >= 0)
|
||||
{
|
||||
pfree(cop); /* The callback structure was invalidated automatically. */
|
||||
vefun_bad_arg(error_index+2, arg-1);
|
||||
/* NOTREACHED */
|
||||
return arg-1;
|
||||
}
|
||||
|
||||
/* We can do the callout.
|
||||
*/
|
||||
|
||||
cop->command_giver = command_giver; /* save current player context */
|
||||
if (command_giver)
|
||||
ref_object(command_giver, "f_call_out"); /* Bump its ref */
|
||||
|
||||
/* Adjust the stack and get the delay */
|
||||
sp = arg - 1;
|
||||
delay = arg[1].u.number;
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
|
||||
/* Insert the new structure at its proper place in the list */
|
||||
|
||||
insert_call(cop, delay);
|
||||
|
||||
return sp;
|
||||
} /* v_call_out() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void
|
||||
call_out (void)
|
||||
|
||||
/* Check if there is any callout due to be called. If yes, do so.
|
||||
* This function is called from the heart_beat handling in the backend.c.
|
||||
* It sets up its own error recovery context so that errors during an
|
||||
* execution won't disturb the rest of the game.
|
||||
*/
|
||||
|
||||
{
|
||||
static int last_time;
|
||||
/* Last time this function was called */
|
||||
|
||||
static struct call *current_call_out;
|
||||
/* Current callout, static so that longjmp() won't clobber it. */
|
||||
|
||||
static object_t *called_object;
|
||||
/* Object last called, static so that longjmp() won't clobber it */
|
||||
|
||||
struct error_recovery_info error_recovery_info;
|
||||
|
||||
/* No calls pending: just update the last_time and return */
|
||||
|
||||
if (call_list == NULL)
|
||||
{
|
||||
last_time = current_time;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If not set yet, initialize last_time on the first call */
|
||||
if (last_time == 0)
|
||||
last_time = current_time;
|
||||
|
||||
/* Update the first .delta in the list (so it won't happen
|
||||
* twice in case of an error.
|
||||
*/
|
||||
call_list->delta -= current_time - last_time;
|
||||
|
||||
last_time = current_time;
|
||||
current_interactive = NULL;
|
||||
|
||||
/* Activate the local error recovery context */
|
||||
|
||||
error_recovery_info.rt.last = rt_context;
|
||||
error_recovery_info.rt.type = ERROR_RECOVERY_BACKEND;
|
||||
rt_context = (rt_context_t *)&error_recovery_info;
|
||||
|
||||
if (setjmp(error_recovery_info.con.text))
|
||||
{
|
||||
/* An error occured: recover and delete the guilty callout */
|
||||
|
||||
struct call *cop;
|
||||
object_t *ob;
|
||||
wiz_list_t *user;
|
||||
|
||||
mark_end_evaluation();
|
||||
clear_state();
|
||||
debug_message("%s Error in call out.\n", time_stamp());
|
||||
cop = current_call_out;
|
||||
ob = called_object;
|
||||
if (ob)
|
||||
{
|
||||
/* Disable the user for this call_out cycle. This is mainly
|
||||
* meant to stop runaway call_outs causing too-long-evaluations.
|
||||
*/
|
||||
user = ob->user;
|
||||
user->call_out_cost = -1;
|
||||
}
|
||||
free_call(cop);
|
||||
}
|
||||
|
||||
/* (Re)initialize stack and tracing */
|
||||
|
||||
tracedepth = 0;
|
||||
|
||||
/* Loop over the call list until it is empty or until all
|
||||
* due callouts are processed.
|
||||
*/
|
||||
while (call_list && call_list->delta <= 0)
|
||||
{
|
||||
object_t *ob;
|
||||
struct call *cop;
|
||||
wiz_list_t *user;
|
||||
|
||||
/* Move the first callout out of the chain.
|
||||
*/
|
||||
cop = call_list;
|
||||
call_list = cop->next;
|
||||
current_call_out = cop;
|
||||
num_callouts--;
|
||||
|
||||
/* A special case:
|
||||
* If a lot of time has passed, so that current call out was missed,
|
||||
* then it will have a negative delta. This negative delta implies
|
||||
* that the next call out in the list has to be adjusted.
|
||||
*/
|
||||
if (cop->delta < 0 && call_list)
|
||||
call_list->delta += cop->delta;
|
||||
|
||||
|
||||
/* Get the object for the function call and make sure it's valid */
|
||||
|
||||
ob = callback_object(&(cop->fun));
|
||||
if (!ob)
|
||||
{
|
||||
/* Nothing to call */
|
||||
free_call(cop);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef USE_SWAP
|
||||
if (O_PROG_SWAPPED(ob)
|
||||
&& load_ob_from_swap(ob) < 0)
|
||||
{
|
||||
debug_message("%s Error in call_out: out of memory: "
|
||||
"unswap object '%s'.\n", time_stamp()
|
||||
, get_txt(ob->name));
|
||||
free_call(cop);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check if the user has exceeded its eval limit for this cycle.
|
||||
* If yes, reschedule the call_out for one second later.
|
||||
*/
|
||||
user = ob->user;
|
||||
if (user->last_call_out == current_time
|
||||
&& user->call_out_cost < 0
|
||||
)
|
||||
{
|
||||
debug_message("%s call_out: user '%s' had an error: "
|
||||
"rescheduling call_out.\n"
|
||||
, time_stamp()
|
||||
, user->name ? get_txt(user->name) : "<null>");
|
||||
insert_call(cop, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Determine the command_giver for the call.
|
||||
* If a command_giver is given in the callout structure, use that one.
|
||||
* Else test the object to be called or the object it's shadowing for
|
||||
* being a command_giver.
|
||||
* Remember that a now-destructed commandgiver is different from having
|
||||
* no commandgiver to begin with.
|
||||
*/
|
||||
if (cop->command_giver)
|
||||
{
|
||||
if (!(cop->command_giver->flags & O_DESTRUCTED))
|
||||
{
|
||||
command_giver = cop->command_giver;
|
||||
if (O_IS_INTERACTIVE(command_giver))
|
||||
trace_level = O_GET_INTERACTIVE(command_giver)->trace_level;
|
||||
}
|
||||
else
|
||||
command_giver = NULL;
|
||||
}
|
||||
#ifdef USE_SHADOWING
|
||||
else if (ob->flags & O_SHADOW)
|
||||
{
|
||||
/* Look at the object which is at the end of the shadow chain.
|
||||
*/
|
||||
shadow_t *shadow_sent;
|
||||
object_t *sob;
|
||||
|
||||
sob = ob;
|
||||
while ((shadow_sent = O_GET_SHADOW(sob)), shadow_sent->shadowing)
|
||||
sob = shadow_sent->shadowing;
|
||||
|
||||
if (sob->flags & O_ENABLE_COMMANDS)
|
||||
{
|
||||
command_giver = sob;
|
||||
if (shadow_sent->ip)
|
||||
trace_level = shadow_sent->ip->trace_level;
|
||||
else
|
||||
trace_level = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
command_giver = NULL;
|
||||
trace_level = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* If at all, this object must be the command_giver */
|
||||
|
||||
if (ob->flags & O_ENABLE_COMMANDS)
|
||||
command_giver = ob;
|
||||
else
|
||||
command_giver = NULL;
|
||||
trace_level = 0;
|
||||
}
|
||||
|
||||
/* Finally, call the function (unless the object was destructed).
|
||||
*/
|
||||
|
||||
called_object = current_object = ob;
|
||||
if (user->last_call_out != current_time)
|
||||
{
|
||||
user->last_call_out = current_time;
|
||||
CLEAR_EVAL_COST;
|
||||
}
|
||||
else
|
||||
assigned_eval_cost = eval_cost = user->call_out_cost;
|
||||
|
||||
mark_start_evaluation();
|
||||
(void)backend_callback(&(cop->fun), 0);
|
||||
user->call_out_cost = eval_cost;
|
||||
mark_end_evaluation();
|
||||
|
||||
/* The function call used up all the arguments, now free
|
||||
* the rest
|
||||
*/
|
||||
free_call(cop);
|
||||
|
||||
} /* while (callouts pending) */
|
||||
|
||||
rt_context = error_recovery_info.rt.last;
|
||||
} /* call_out() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void
|
||||
find_call_out (object_t *ob, svalue_t *fun, Bool do_free_call)
|
||||
|
||||
/* Find the (first) callout for <ob>/<fun> (or <fun> if it is a closure).
|
||||
* If <do_free_call> is true, the found callout is removed.
|
||||
*
|
||||
* In either case, *<fun> is modified into a NUMBER holding the time left
|
||||
* for the found/removed callout. If no callout was found, -1 is returned.
|
||||
*/
|
||||
|
||||
{
|
||||
struct call **copp, *cop;
|
||||
int delay = 0;
|
||||
string_t *fun_name;
|
||||
|
||||
/* Find callout by closure */
|
||||
|
||||
if (fun->type != T_STRING)
|
||||
{
|
||||
if (fun->type == T_CLOSURE)
|
||||
{
|
||||
for (copp = &call_list; NULL != (cop = *copp); copp = &cop->next)
|
||||
{
|
||||
delay += cop->delta;
|
||||
if (cop->fun.is_lambda
|
||||
&& closure_eq(&(cop->fun.function.lambda), fun)
|
||||
)
|
||||
{
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
free_svalue(fun);
|
||||
put_number(fun, -1);
|
||||
return;
|
||||
found:
|
||||
free_svalue(fun);
|
||||
if (do_free_call)
|
||||
{
|
||||
if (cop->next)
|
||||
cop->next->delta += cop->delta;
|
||||
*copp = cop->next;
|
||||
free_call(cop);
|
||||
num_callouts--;
|
||||
}
|
||||
/* It is possible to have delay < 0 if we are
|
||||
* called from inside call_out() .
|
||||
*/
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
put_number(fun, delay);
|
||||
return;
|
||||
}
|
||||
fatal("find_call_out() got %s, expected string/closure.\n"
|
||||
, typename(fun->type));
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
|
||||
/* Find callout by object/name */
|
||||
|
||||
fun_name = find_tabled(fun->u.str);
|
||||
|
||||
if (fun_name != NULL)
|
||||
for (copp = &call_list; NULL != (cop = *copp); copp = &cop->next)
|
||||
{
|
||||
delay += cop->delta;
|
||||
if (cop->fun.function.named.ob == ob
|
||||
&& cop->fun.function.named.name == fun_name
|
||||
&& !cop->fun.is_lambda)
|
||||
{
|
||||
if (do_free_call)
|
||||
{
|
||||
if (cop->next)
|
||||
cop->next->delta += cop->delta;
|
||||
*copp = cop->next;
|
||||
free_call(cop);
|
||||
num_callouts--;
|
||||
}
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
free_svalue(fun);
|
||||
put_number(fun, delay);
|
||||
return;
|
||||
}
|
||||
} /* if()for() */
|
||||
|
||||
/* Not found */
|
||||
free_svalue(fun);
|
||||
put_number(fun, -1);
|
||||
} /* find_call_out() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
size_t
|
||||
call_out_status (strbuf_t *sbuf, Bool verbose)
|
||||
|
||||
/* Compute and return the amount of memory used by callouts.
|
||||
* If <verbose> is true, write detailed statistics to the current user.
|
||||
*/
|
||||
|
||||
{
|
||||
remove_stale_call_outs();
|
||||
if (verbose)
|
||||
{
|
||||
strbuf_add(sbuf, "\nCall out information:\n");
|
||||
strbuf_add(sbuf,"---------------------\n");
|
||||
strbuf_addf(sbuf, "Number of call outs: %8ld, %8ld bytes\n",
|
||||
num_callouts, num_callouts * sizeof (struct call));
|
||||
}
|
||||
else
|
||||
{
|
||||
strbuf_addf(sbuf, "call out:\t\t\t%8ld %9ld\n"
|
||||
, num_callouts, num_callouts * sizeof (struct call));
|
||||
}
|
||||
|
||||
return num_callouts * sizeof (struct call);
|
||||
} /* call_out_status() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void
|
||||
callout_dinfo_status (svalue_t *svp, int value)
|
||||
|
||||
/* Return the callout information for debug_info(DINFO_DATA, DID_STATUS).
|
||||
* <svp> points to the svalue block for the result, this function fills in
|
||||
* the spots for the object table.
|
||||
* If <value> is -1, <svp> points indeed to a value block; other it is
|
||||
* the index of the desired value and <svp> points to a single svalue.
|
||||
*/
|
||||
|
||||
{
|
||||
#define ST_NUMBER(which,code) \
|
||||
if (value == -1) svp[which].u.number = code; \
|
||||
else if (value == which) svp->u.number = code
|
||||
|
||||
remove_stale_call_outs();
|
||||
ST_NUMBER(DID_ST_CALLOUTS, num_callouts);
|
||||
ST_NUMBER(DID_ST_CALLOUT_SIZE, num_callouts * sizeof(struct call));
|
||||
|
||||
#undef ST_NUMBER
|
||||
} /* callout_dinfo_status() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
#ifdef USE_PARANOIA
|
||||
|
||||
void
|
||||
count_extra_ref_from_call_outs (void)
|
||||
|
||||
/* Used to debug refcounts: count all refcounts in the callout handling.
|
||||
*/
|
||||
|
||||
{
|
||||
struct call *cop;
|
||||
|
||||
for (cop = call_list; cop; cop = cop->next)
|
||||
{
|
||||
count_callback_extra_refs(&(cop->fun));
|
||||
if (cop->command_giver)
|
||||
count_extra_ref_in_object(cop->command_giver);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void
|
||||
remove_stale_call_outs (void)
|
||||
|
||||
/* GC and statistics support: Remove all callouts referencing destructed
|
||||
* objects.
|
||||
*/
|
||||
|
||||
{
|
||||
struct call **copp, *cop;
|
||||
|
||||
for (copp = &call_list; NULL != (cop = *copp); )
|
||||
{
|
||||
object_t *ob;
|
||||
|
||||
ob = callback_object(&(cop->fun));
|
||||
if (!ob)
|
||||
{
|
||||
num_callouts--;
|
||||
if (cop->next)
|
||||
cop->next->delta += cop->delta;
|
||||
*copp = cop->next;
|
||||
free_call(cop);
|
||||
continue;
|
||||
}
|
||||
copp = &cop->next;
|
||||
}
|
||||
} /* remove_stale_call_outs() */
|
||||
|
||||
|
||||
#ifdef GC_SUPPORT
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void
|
||||
clear_ref_from_call_outs (void)
|
||||
|
||||
/* GC Support: Clear all refs from the callout handling.
|
||||
*/
|
||||
|
||||
{
|
||||
struct call *cop;
|
||||
|
||||
for (cop = call_list; cop; cop = cop->next)
|
||||
{
|
||||
object_t *ob;
|
||||
|
||||
clear_ref_in_callback(&(cop->fun));
|
||||
|
||||
if (NULL != (ob = cop->command_giver))
|
||||
clear_object_ref(ob);
|
||||
}
|
||||
} /* clear_ref_from_call_outs() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void
|
||||
count_ref_from_call_outs (void)
|
||||
|
||||
/* GC Support: Clear all refs from the callout handling.
|
||||
*/
|
||||
|
||||
{
|
||||
struct call *cop;
|
||||
object_t *ob;
|
||||
|
||||
for (cop = call_list; cop; cop = cop->next)
|
||||
{
|
||||
count_ref_in_callback(&(cop->fun));
|
||||
|
||||
if ( NULL != (ob = cop->command_giver) )
|
||||
{
|
||||
if (ob->flags & O_DESTRUCTED) {
|
||||
reference_destructed_object(ob);
|
||||
cop->command_giver = NULL;
|
||||
} else {
|
||||
ob->ref++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* count_ref_from_call_outs() */
|
||||
|
||||
#endif /* GC_SUPPORT */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static vector_t *
|
||||
get_all_call_outs (void)
|
||||
|
||||
/* Construct an array of all pending call_outs (whose object is not
|
||||
* destructed). Every item in the array is itself an array of 4 or
|
||||
* more entries:
|
||||
* 0: The object (only if the function is a string).
|
||||
* 1: The function (string or closure).
|
||||
* 2: The delay.
|
||||
* 3..: The argument(s).
|
||||
*/
|
||||
{
|
||||
int i, next_time;
|
||||
struct call *cop;
|
||||
vector_t *v;
|
||||
|
||||
/* Count the number of pending callouts and allocate
|
||||
* the result array.
|
||||
*/
|
||||
for (i = 0, cop = call_list; cop; cop = cop->next)
|
||||
{
|
||||
if (!callback_object(&(cop->fun)))
|
||||
continue;
|
||||
i++;
|
||||
}
|
||||
v = allocate_array(i); /* assume that all elements are inited to 0 */
|
||||
|
||||
/* Create the result array contents.
|
||||
*/
|
||||
|
||||
next_time = 0;
|
||||
for (i=0, cop = call_list; cop; cop = cop->next)
|
||||
{
|
||||
vector_t *vv;
|
||||
object_t *ob;
|
||||
|
||||
next_time += cop->delta;
|
||||
|
||||
ob = callback_object(&(cop->fun));
|
||||
if (!ob)
|
||||
continue;
|
||||
|
||||
/* Get the subarray */
|
||||
|
||||
vv = allocate_array(3 + cop->fun.num_arg);
|
||||
|
||||
if (cop->fun.is_lambda)
|
||||
{
|
||||
if (cop->fun.function.lambda.x.closure_type == CLOSURE_LFUN)
|
||||
put_ref_object( vv->item
|
||||
, cop->fun.function.lambda.u.lambda->function.lfun.ob
|
||||
, "get_all_call_outs");
|
||||
else
|
||||
put_ref_object(vv->item, ob, "get_all_call_outs");
|
||||
assign_svalue_no_free(&vv->item[1], &cop->fun.function.lambda);
|
||||
}
|
||||
else
|
||||
{
|
||||
put_ref_object(vv->item, ob, "get_all_call_outs");
|
||||
put_ref_string(vv->item + 1, cop->fun.function.named.name);
|
||||
}
|
||||
|
||||
vv->item[2].u.number = next_time;
|
||||
|
||||
if (cop->fun.num_arg > 0)
|
||||
{
|
||||
svalue_t *source, *dest;
|
||||
int nargs;
|
||||
|
||||
nargs = cop->fun.num_arg;
|
||||
if (nargs > 1)
|
||||
source = cop->fun.arg.u.lvalue;
|
||||
else
|
||||
source = &(cop->fun.arg);
|
||||
dest = &vv->item[3];
|
||||
do {
|
||||
assign_svalue_no_free(dest++, source++);
|
||||
} while (--nargs);
|
||||
}
|
||||
|
||||
put_array(v->item + i, vv);
|
||||
i++;
|
||||
}
|
||||
|
||||
return v;
|
||||
} /* get_all_call_outs() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
svalue_t *
|
||||
f_call_out_info (svalue_t *sp)
|
||||
|
||||
/* EFUN call_out_info()
|
||||
*
|
||||
* mixed *call_out_info(void)
|
||||
*
|
||||
* Get information about all pending call outs. The result is an
|
||||
* array in which every entry is itself an array describing one
|
||||
* call_out.
|
||||
*
|
||||
* The efun causes the the privilege violation ("call_out_info",
|
||||
* this_object()). If it is not satisfied, the result will be
|
||||
* the empty array.
|
||||
*/
|
||||
|
||||
{
|
||||
if (privilege_violation(STR_CALL_OUT_INFO, &const0, sp))
|
||||
{
|
||||
push_array(sp, get_all_call_outs());
|
||||
}
|
||||
else
|
||||
{
|
||||
push_ref_array(sp, &null_vector);
|
||||
}
|
||||
|
||||
return sp;
|
||||
} /* f_call_out_info() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
svalue_t *
|
||||
f_find_call_out (svalue_t *sp)
|
||||
|
||||
/* EFUN find_call_out()
|
||||
*
|
||||
* int find_call_out(string func)
|
||||
* int find_call_out(closure func)
|
||||
*
|
||||
* Find the first call-out due to be executed for function func
|
||||
* in the current object, and return the time left. If no call-out
|
||||
* is found return -1.
|
||||
*/
|
||||
|
||||
{
|
||||
find_call_out(current_object, sp, MY_FALSE);
|
||||
return sp;
|
||||
} /* f_find_call_out() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
svalue_t *
|
||||
f_remove_call_out (svalue_t *sp)
|
||||
|
||||
/* EFUN remove_call_out()
|
||||
*
|
||||
* int remove_call_out(string fun)
|
||||
* int remove_call_out(closure fun)
|
||||
*
|
||||
* Remove next pending call-out for function fun in this object.
|
||||
* The time left is returned.
|
||||
*
|
||||
* -1 is returned if there were no call-outs pending to this
|
||||
* function.
|
||||
*/
|
||||
|
||||
{
|
||||
find_call_out(current_object, sp, MY_TRUE);
|
||||
return sp;
|
||||
} /* f_remove_call_out() */
|
||||
|
||||
/***************************************************************************/
|
||||
|
29
src/call_out.h
Normal file
29
src/call_out.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef CALL_OUT_H__
|
||||
#define CALL_OUT_H__ 1
|
||||
|
||||
#include "driver.h"
|
||||
#include "typedefs.h"
|
||||
#include "strfuns.h" /* strbuf_t */
|
||||
|
||||
/* --- Prototypes --- */
|
||||
|
||||
extern void call_out(void);
|
||||
extern size_t call_out_status(strbuf_t *sbuf, Bool verbose);
|
||||
extern void callout_dinfo_status(svalue_t *svp, int value);
|
||||
extern void remove_stale_call_outs(void);
|
||||
|
||||
extern svalue_t *v_call_out(svalue_t *sp, int num_arg);
|
||||
extern svalue_t *f_call_out_info(svalue_t *sp);
|
||||
extern svalue_t *f_find_call_out(svalue_t *sp);
|
||||
extern svalue_t *f_remove_call_out(svalue_t *sp);
|
||||
|
||||
#ifdef DEBUG
|
||||
extern void count_extra_ref_from_call_outs(void);
|
||||
#endif
|
||||
|
||||
#ifdef GC_SUPPORT
|
||||
extern void clear_ref_from_call_outs(void);
|
||||
extern void count_ref_from_call_outs(void);
|
||||
#endif
|
||||
|
||||
#endif /* CALL_OUT_H__ */
|
7154
src/closure.c
Normal file
7154
src/closure.c
Normal file
File diff suppressed because it is too large
Load diff
144
src/closure.h
Normal file
144
src/closure.h
Normal file
|
@ -0,0 +1,144 @@
|
|||
#ifndef CLOSURE_H__
|
||||
#define CLOSURE_H__ 1
|
||||
|
||||
#include "driver.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
#include "bytecode.h"
|
||||
#ifdef USE_NEW_INLINES
|
||||
#include "svalue.h"
|
||||
#endif /* USE_NEW_INLINES */
|
||||
|
||||
/* --- Types --- */
|
||||
|
||||
/* --- struct lambda_s: ---
|
||||
*
|
||||
* If the closure uses constant values, they are stored in an svalue[]
|
||||
* right before the struct lambda and indexed from the end.
|
||||
* For lfun closures, the context variables are stored after the
|
||||
* lambda_s. If the lfun closure has no context variables, or for
|
||||
* other kinds of closures the context[] part is not allocated at all.
|
||||
*/
|
||||
|
||||
struct lambda_s
|
||||
{
|
||||
/* svalue_t values[]
|
||||
*
|
||||
* For lambda closures, the constant values used by the function
|
||||
* which are indexed from the end. That means that value #x can
|
||||
* be found at address ((svalue_t *)lambda_t)[-x-1].
|
||||
*/
|
||||
|
||||
p_int ref; /* ref count */
|
||||
object_t *ob;
|
||||
/* Object the closure is bound to (for bound UNBOUND_LAMBDAs just
|
||||
* during the execution of the lambda).
|
||||
*/
|
||||
|
||||
object_t *prog_ob;
|
||||
ptrdiff_t prog_pc;
|
||||
/* Blueprint object and relative for the program creating this closure,
|
||||
* or NULL. Since this information is error reporting purposes only,
|
||||
* the lambda keeps a reference to the blueprint and not the program
|
||||
* itself to not get in the way of swapping or other things.
|
||||
*/
|
||||
|
||||
union /* Closure information: */
|
||||
{
|
||||
unsigned short var_index;
|
||||
/* _IDENTIFIER: index in the variable table
|
||||
*/
|
||||
# define VANISHED_VARCLOSURE_INDEX ((unsigned short)-1)
|
||||
/* Special value for vanished variable closures.
|
||||
* TODO: it's tested with >=0 at places :-(,
|
||||
*/
|
||||
|
||||
struct {
|
||||
/* CLOSURE_LFUN */
|
||||
object_t *ob; /* Originating object */
|
||||
unsigned short index; /* Index in the object's function
|
||||
* table */
|
||||
program_t *inhProg; /* NULL or the program containing
|
||||
* the function for closure
|
||||
* referencing inherited functions
|
||||
* (even if overloaded).
|
||||
*/
|
||||
unsigned short context_size; /* Number of context vars */
|
||||
} lfun;
|
||||
|
||||
bytecode_t code[1];
|
||||
/* LAMBDA and UNBOUND_LAMBDA closures: the function code, starting
|
||||
* with uint8 'num_values' and continuing with FUNCTION_NUM_ARGS
|
||||
* (which is where the fun_hdr_p will point to).
|
||||
* 'num_values' is the size of the svalue[] preceeding the lambda;
|
||||
* if it is 0xff, the actual size is stored in
|
||||
* svalue[-0xff].u.number.
|
||||
*/
|
||||
# define LAMBDA_NUM_VALUES(p) EXTRACT_UCHAR((char *)p)
|
||||
# define LAMBDA_NUM_ARGS(p) EXTRACT_SCHAR((char *)p + sizeof(char))
|
||||
# define LAMBDA_NUM_VARS(p) (*((unsigned char *)((char *)p + 2*sizeof(char))))
|
||||
# define LAMBDA_CODE(p) ((bytecode_p)((unsigned char *)p + 3*sizeof(char)))
|
||||
|
||||
lambda_t *lambda;
|
||||
/* BOUND_LAMBDA: pointer to the UNBOUND_LAMBDA structure.
|
||||
*/
|
||||
} function;
|
||||
|
||||
#ifdef USE_NEW_INLINES
|
||||
svalue_t context[ /* .lfun.context_size */ 1];
|
||||
/* lfun-closure context variables, if any.
|
||||
* Putting this array into the function.lfun somehow causes memory
|
||||
* corruption because some lambda structures won't be allocated large
|
||||
* enough.
|
||||
*/
|
||||
#endif
|
||||
};
|
||||
|
||||
#define LAMBDA_VALUE_OFFSET \
|
||||
(sizeof(svalue_t) + offsetof(lambda_t, function.code[1]))
|
||||
/* Offset from the fun_hdr_p of a lambda closure to the first
|
||||
* constant value (the one with index number 0).
|
||||
*/
|
||||
|
||||
#ifndef USE_NEW_INLINES
|
||||
#define SIZEOF_LAMBDA(num) sizeof(struct lambda_s)
|
||||
#else /* USE_NEW_INLINES */
|
||||
#define SIZEOF_LAMBDA(num) (sizeof(struct lambda_s) + (((int)num)-1) * sizeof(svalue_t))
|
||||
#endif /* USE_NEW_INLINES */
|
||||
/* size_t SIZEOF_LAMBDA(int num)
|
||||
* Size of a lambda closure with <num> context variables.
|
||||
*/
|
||||
|
||||
/* --- Prototypes --- */
|
||||
|
||||
extern long find_function(const string_t *name, const program_t *prog);
|
||||
extern Bool closure_eq (svalue_t * left, svalue_t * right);
|
||||
extern int closure_cmp (svalue_t * left, svalue_t * right);
|
||||
extern void set_closure_user(svalue_t *svp, object_t *owner);
|
||||
extern void replace_program_lambda_adjust(replace_ob_t *r_ob);
|
||||
extern void closure_init_lambda (lambda_t * l, object_t * obj);
|
||||
#ifndef USE_NEW_INLINES
|
||||
extern void closure_literal(svalue_t *dest, int ix, unsigned short inhIndex);
|
||||
extern void closure_lfun (svalue_t *dest, object_t *obj, program_t *prog, int ix, Bool raise_error);
|
||||
extern lambda_t *closure_new_lambda (object_t * obj, Bool raise_error);
|
||||
#else /* USE_NEW_INLINES */
|
||||
extern lambda_t *closure_new_lambda (object_t * obj, unsigned short context_size, Bool raise_error);
|
||||
extern void closure_lfun (svalue_t *dest, object_t *obj, program_t *prog, int ix, unsigned short num, Bool raise_error);
|
||||
extern void closure_literal(svalue_t *dest, int ix, unsigned short inhIndex, unsigned short num);
|
||||
#endif /* USE_NEW_INLINES */
|
||||
extern void closure_identifier (svalue_t *dest, object_t * obj, int ix, Bool raise_error);
|
||||
extern void free_closure(svalue_t *svp);
|
||||
extern Bool is_undef_closure (svalue_t *sp);
|
||||
extern void closure_lookup_lfun_prog ( lambda_t * l , program_t ** pProg , string_t ** pName , Bool * pIsInherited);
|
||||
extern const char * closure_operator_to_string (int type);
|
||||
extern const char * closure_efun_to_string (int type);
|
||||
extern string_t * closure_location (lambda_t *l);
|
||||
extern string_t *closure_to_string (svalue_t * sp, Bool compact);
|
||||
extern svalue_t *v_bind_lambda(svalue_t *sp, int num_arg);
|
||||
extern svalue_t *f_lambda(svalue_t *sp);
|
||||
extern svalue_t *f_symbol_function(svalue_t *sp);
|
||||
extern svalue_t *f_symbol_variable(svalue_t *sp);
|
||||
extern svalue_t *f_unbound_lambda(svalue_t *sp);
|
||||
extern void align_switch(bytecode_p pc);
|
||||
|
||||
#endif /* CLOSURE_H__ */
|
9428
src/comm.c
Normal file
9428
src/comm.c
Normal file
File diff suppressed because it is too large
Load diff
487
src/comm.h
Normal file
487
src/comm.h
Normal file
|
@ -0,0 +1,487 @@
|
|||
#ifndef COMM_H__
|
||||
#define COMM_H__ 1
|
||||
|
||||
#include "driver.h"
|
||||
#include "typedefs.h"
|
||||
#include <sys/types.h>
|
||||
#ifdef USE_PTHREADS
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
#ifdef USE_MCCP
|
||||
# include <zlib.h>
|
||||
#endif
|
||||
|
||||
#include "simulate.h" /* callback_t for input_to_t */
|
||||
#include "svalue.h"
|
||||
#include "pkg-tls.h"
|
||||
|
||||
/* TODO: Make the following a separate "my-socket.h" include, also
|
||||
* TODO:: to be used in access_check.h instead of comm.h.
|
||||
*/
|
||||
#ifdef SOCKET_HEADER
|
||||
# include SOCKET_HEADER
|
||||
#endif
|
||||
|
||||
#if !defined (SOCKET_LIB) && !defined(SOCKET_INC)
|
||||
# include <sys/socket.h>
|
||||
# ifdef _AIX
|
||||
# include <sys/socketvar.h>
|
||||
# endif
|
||||
# include <netinet/in.h>
|
||||
# include <arpa/inet.h>
|
||||
# define SOCKET_T int
|
||||
#endif /* SOCKET_LIB */
|
||||
|
||||
#ifndef MAX_SOCKET_PACKET_SIZE
|
||||
# if defined(sgi) && defined(mips) && defined(unix)
|
||||
/* Work around for an irix kernel bug that can leave the
|
||||
* process unresponsive and unkillable.
|
||||
*/
|
||||
# define MAX_SOCKET_PACKET_SIZE 200
|
||||
# else
|
||||
# define MAX_SOCKET_PACKET_SIZE 1024 /* Wild guess. */
|
||||
# endif /* irix */
|
||||
#endif /* MAX_SOCKET_PACKET_SIXE */
|
||||
|
||||
|
||||
/* --- IPv6 --- */
|
||||
|
||||
#ifdef USE_IPV6
|
||||
|
||||
/* For IPv6 we defined macros for the 'old' sockaddr member names
|
||||
* which expand into the ipv6 names.
|
||||
*/
|
||||
|
||||
#define sockaddr_in sockaddr_in6
|
||||
|
||||
#define sin_port sin6_port
|
||||
#define sin_addr sin6_addr
|
||||
#define sin_family sin6_family
|
||||
#define s_addr s6_addr
|
||||
#define in_addr in6_addr
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__) && !defined(s6_addr32)
|
||||
|
||||
/* These are non-standard defines, and some OS don't offer them
|
||||
* by default: OS-X
|
||||
*/
|
||||
|
||||
# define s6_addr8 __u6_addr.__u6_addr8
|
||||
# define s6_addr16 __u6_addr.__u6_addr16
|
||||
# define s6_addr32 __u6_addr.__u6_addr32
|
||||
#endif
|
||||
|
||||
#endif /* USE_IPV6 */
|
||||
|
||||
|
||||
/* --- Macros --- */
|
||||
|
||||
/* 'Format string' to use with add_message() when sending
|
||||
* a string_t* string to the player.
|
||||
*/
|
||||
|
||||
#define FMT_STRING ((const char *)&add_message)
|
||||
|
||||
/* 'Format string' to use with add_message() when sending
|
||||
* a string with binary characters and of fixed size
|
||||
* to the player.
|
||||
*/
|
||||
|
||||
#define FMT_BINARY (FMT_STRING+1)
|
||||
|
||||
/* --- Telnet Handling --- */
|
||||
|
||||
#define SEND_TELNET_COMMAND(TEXT) {\
|
||||
sending_telnet_command = MY_TRUE;\
|
||||
TEXT\
|
||||
sending_telnet_command = MY_FALSE;\
|
||||
}
|
||||
/* Use this macro to safely send telnet commands with TEXT
|
||||
*/
|
||||
|
||||
#ifdef DEBUG_TELNET
|
||||
|
||||
#define DT(x) printf("%s TDEBUG: ", time_stamp()); printf x
|
||||
#define DTN(x) printf("%s TDEBUG: '%s' ", time_stamp(), get_txt(ip->ob->name)); printf x
|
||||
#define DTF(x) printf x
|
||||
|
||||
#else
|
||||
|
||||
#define DT(x)
|
||||
#define DTN(x)
|
||||
#define DTF(x)
|
||||
|
||||
#endif
|
||||
|
||||
/* --- Types --- */
|
||||
|
||||
/* --- struct write_buffer_s: async write datastructure
|
||||
*
|
||||
* This data structure holds all the information for pending messages
|
||||
* which are to be written by a background thread. The structure is
|
||||
* allocated to the necessary length to hold the full message.
|
||||
* The instances are kept in a linked list from the interactive_t
|
||||
* structure.
|
||||
*/
|
||||
#ifdef USE_PTHREADS
|
||||
struct write_buffer_s
|
||||
{
|
||||
struct write_buffer_s *next;
|
||||
size_t length;
|
||||
Bool compress; /* should the buffer get compressed by mccp? */
|
||||
int errorno; /* After writing, the errno */
|
||||
char buffer[1 /* .length */ ];
|
||||
};
|
||||
#endif
|
||||
|
||||
/* --- struct input_to_s: input_to() datastructure
|
||||
*
|
||||
* input-to structures describe a pending input_to() for a given
|
||||
* interactive object. Every object can have one input-to pending, the
|
||||
* pointer to the structure is stored in the interactive sentence structure.
|
||||
*/
|
||||
|
||||
struct input_to_s {
|
||||
input_to_t *next;
|
||||
svalue_t prompt; /* the prompt, may be 0 */
|
||||
char noecho; /* the requested "noecho" state */
|
||||
Bool local; /* TRUE if a CHARMODE change is local only */
|
||||
callback_t fun; /* The function to call, and its args */
|
||||
};
|
||||
|
||||
/* --- struct interactive_s: an interactive connection
|
||||
*
|
||||
* The structure is linked to by a shadow sentence of the interactive
|
||||
* object.
|
||||
*
|
||||
* When changing struct members, take care that you don't introduce
|
||||
* unnecessary padding.
|
||||
*/
|
||||
|
||||
struct interactive_s {
|
||||
SOCKET_T socket; /* The socket structure */
|
||||
object_t *ob; /* Points back to the associated object */
|
||||
input_to_t *input_to; /* != NULL: defines function to be
|
||||
called with next input line */
|
||||
object_t *modify_command; /* modify_command() handler() */
|
||||
svalue_t prompt; /* The prompt to print. */
|
||||
struct sockaddr_in addr; /* Address of connected user */
|
||||
|
||||
CBool msg_discarded; /* True if an earlier msg had been discarded */
|
||||
CBool set_input_to; /* True if input_to was set in this cycle */
|
||||
CBool closing; /* True when closing this socket. */
|
||||
CBool tn_enabled; /* True: telnet machine enabled */
|
||||
#ifdef USE_EXPERIMENTAL
|
||||
CBool is_binary; /* True: socket reads binary */
|
||||
#endif
|
||||
char do_close; /* Bitflags: Close this down; Proto-ERQ. */
|
||||
char noecho; /* Input mode bitflags */
|
||||
|
||||
char tn_state; /* current state of telnet machine */
|
||||
char save_tn_state; /* saved state of telnet machine */
|
||||
CBool supress_go_ahead; /* Keep track of the WILL SGA negotiation state
|
||||
* as some clients mix that up with DO SGA.
|
||||
* Other than that, this is of no concern.
|
||||
*/
|
||||
CBool outgoing_conn; /* TRUE if the connection was created by
|
||||
* net_connect().
|
||||
*/
|
||||
|
||||
int text_end; /* first free char in buffer */
|
||||
int command_start; /* used for charmode */
|
||||
int command_end; /* where we are up to in player cmd buffer */
|
||||
int tn_start; /* first char of pending telnet neg */
|
||||
int tn_end; /* first char to check for telnet negotiation */
|
||||
int32 chars_ready; /* amount of pure data available. In charmode
|
||||
* this is the amount of data already echoed
|
||||
* back to the sender. */
|
||||
#ifdef USE_SNOOPING
|
||||
interactive_t *snoop_on; /* whom we're snooping */
|
||||
object_t *snoop_by; /* by whom we're snooped */
|
||||
#endif
|
||||
mp_int last_time; /* Time of last command executed */
|
||||
long numCmds; /* Number of commands executed with the same
|
||||
* .last_time */
|
||||
long maxNumCmds; /* Maximum number of commands (char or line)
|
||||
* to execute per second. A value < 0
|
||||
* means 'unlimited'.
|
||||
*/
|
||||
int trace_level; /* Trace flags. 0 means no tracing */
|
||||
string_t *trace_prefix; /* Trace only objects which have this string
|
||||
as name prefix. NULL traces everything. */
|
||||
int message_length; /* Current length of message in message_buf[] */
|
||||
|
||||
object_t *next_player_for_flush;
|
||||
object_t *previous_player_for_flush;
|
||||
/* Double linked list of all active user objects with data pending
|
||||
* in message_buf[].
|
||||
*/
|
||||
|
||||
long access_class;
|
||||
/* represents a "cluster" where this player comes from
|
||||
*/
|
||||
char charset[32];
|
||||
/* A bitflag array: every non-zero flag allows the corresponding
|
||||
* character to be sent. Characters whose flag is 0 are excluded
|
||||
* from the sent data.
|
||||
*/
|
||||
char combine_cset[32];
|
||||
/* A bitflag array: all characters with their corresponding flag
|
||||
* set to non-zero flag may be combined into one string in
|
||||
* char-mode when received en-bloc anyway. Characters whose flag
|
||||
* is 0 are always returned in charmode in separate strings.
|
||||
* TODO: The code for these two thingies assume 8 Bits per character.
|
||||
*/
|
||||
CBool quote_iac;
|
||||
CBool catch_tell_activ;
|
||||
char gobble_char; /* Char to ignore at the next telnet_neg() */
|
||||
char ts_data; /* Telnet suboption? */
|
||||
|
||||
char text[MAX_TEXT+2];
|
||||
/* The receive buffer. It can contain two extra characters:
|
||||
* a '\r' that is recognized only after another character is read,
|
||||
* and a terminating '\0'.
|
||||
*/
|
||||
|
||||
char message_buf[MAX_SOCKET_PACKET_SIZE];
|
||||
/* The send buffer. */
|
||||
|
||||
#ifdef USE_MCCP
|
||||
unsigned char compressing;
|
||||
z_stream * out_compress;
|
||||
unsigned char * out_compress_buf;
|
||||
#endif
|
||||
|
||||
#ifdef USE_PTHREADS
|
||||
/* The data exchange with the writer thread happens through two
|
||||
* lists: write_first/write_last hands of data to write to
|
||||
* the thread, written_first receives the written buffers.
|
||||
* Reason for this 2-way exchange is that the writer thread
|
||||
* must not call xfree().
|
||||
* TODO: These two lists + one extra can be combined into
|
||||
* TODO:: one list, plus two roving pointers into it.
|
||||
* TODO:: In fact, once ptmalloc is really complete, the buffers
|
||||
* TODO:: can be discarded immediately and the written_first list
|
||||
* TODO:: becomes unnecessary.
|
||||
*/
|
||||
Bool flush_on_cleanup;
|
||||
/* If set to TRUE at the time the thread is cancelled, all remaining
|
||||
* pending data is sent to the socket (which is made non-blocking for
|
||||
* this) as part of the cleanup.
|
||||
*/
|
||||
pthread_mutex_t write_mutex;
|
||||
pthread_cond_t write_cond;
|
||||
pthread_t write_thread;
|
||||
struct write_buffer_s *write_first; /* List of buffers to write */
|
||||
struct write_buffer_s *write_last;
|
||||
unsigned long write_size;
|
||||
struct write_buffer_s *write_current; /* Buffer currently written */
|
||||
struct write_buffer_s *written_first; /* List of written buffers */
|
||||
#endif
|
||||
|
||||
#ifdef USE_TLS
|
||||
tls_session_t tls_session;
|
||||
int tls_status;
|
||||
# define TLS_INACTIVE 0 /* Session is not secure */
|
||||
# define TLS_HANDSHAKING 1 /* TLS is being negotiated */
|
||||
# define TLS_ACTIVE 2 /* Session is secure */
|
||||
# define TLS_BROKEN 3 /* Error has occurred */
|
||||
CBool tls_want_peer_cert;
|
||||
# ifdef USE_EXPERIMENTAL
|
||||
CBool tls_autodetect;
|
||||
# endif
|
||||
callback_t *tls_cb;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* --- Bitflags and masks for interactive.noecho ---
|
||||
*
|
||||
* 'noecho' is a historical misnomer as it actually represents several
|
||||
* input modes: echo/noecho, linemode/charmode, and ignore '!' escape.
|
||||
* Echo and Charmode additionally distinguish between 'required'
|
||||
* and 'granted' ('want yes' and 'yes').
|
||||
*
|
||||
* xxx_REQ is set when the lib wants this state (independend from telnet state)
|
||||
* xxx is set when we sent out the appropirate negotiations
|
||||
* xxx_ACK is set when the client agrees
|
||||
*
|
||||
* xxx xxx_ACK telnet state
|
||||
* 0 0 NO
|
||||
* 1 0 WANT YES
|
||||
* 1 1 YES
|
||||
* 0 1 WANT NO (not implemented)
|
||||
*/
|
||||
|
||||
#define CHARMODE_REQ_TO_CHARMODE(x) ((x) << 2)
|
||||
/* Transform {CHARMODE, NOECHO}_REQ into {CHARMODE, NOECHO}
|
||||
*/
|
||||
#define NOECHO_ACKSHIFT(x) ((x) << 2)
|
||||
#define NOECHO_ACKRSHIFT(x) ((x) >> 2)
|
||||
/* TODO: ???
|
||||
*/
|
||||
|
||||
#define IGNORE_BANG 128
|
||||
/* Disable input escape with leading '!'.
|
||||
*/
|
||||
|
||||
#define NOECHO_REQ 1
|
||||
/* noecho requested
|
||||
*/
|
||||
#define NOECHO /* 4 */ CHARMODE_REQ_TO_CHARMODE(NOECHO_REQ)
|
||||
/* noecho active (requested via telnet negotiation)
|
||||
*/
|
||||
#define NOECHO_ACK /* 16 */ NOECHO_ACKSHIFT(NOECHO)
|
||||
/* noecho negotiation complete (acknowledged)
|
||||
* TODO: We need a _NACK flag, too, for when the negotiation is complete
|
||||
* TODO:: but the client refused to go into NOECHO. For the time being
|
||||
* TODO:: we might use (NOECHO_REQ|NOECHO) == (NOECHO_REQ) as check.
|
||||
*/
|
||||
#define NOECHO_STALE 64
|
||||
/* Set prior to performing a noecho input, this bit causes the deactivation
|
||||
* of noecho if still set after the input (ie if noecho was not requested
|
||||
* again).
|
||||
*/
|
||||
#define NOECHO_MASK (NOECHO|NOECHO_ACK)
|
||||
/* Mask for active noecho states.
|
||||
*/
|
||||
|
||||
#define CHARMODE_REQ 2
|
||||
/* Charmode requested
|
||||
* The driver orients its behaviour according to this flag so that it
|
||||
* can act correctly even before the negotiation is complete.
|
||||
* Moreover, this flag serves as indicator that the input buffer
|
||||
* variables are set up to 'charmode', so it should not be reset except
|
||||
* through a call to set_noecho().
|
||||
*/
|
||||
#define CHARMODE /* 8 */ CHARMODE_REQ_TO_CHARMODE(CHARMODE_REQ)
|
||||
/* Charmode active (requested via telnet negotiation)
|
||||
*/
|
||||
#define CHARMODE_ACK /* 32 */ NOECHO_ACKSHIFT(CHARMODE)
|
||||
/* Charmode negotiation complete (acknowledged)
|
||||
* TODO: We need a _NACK flag, too, for when the negotiation is complete
|
||||
* TODO:: but the client refused to go into CHARMODE. For the time being
|
||||
* TODO:: we can use (CHARMODE_REQ|CHARMODE) == CHARMODE_REQ as check.
|
||||
*/
|
||||
#define NOECHO_DELAYED 128
|
||||
/* If NOECHO and CHARMODE is requested, we first try to establish
|
||||
* CHARMODE and set this flag. If CHARMODE is acknoledged we try to
|
||||
* negotiate for NOECHO. This modus operandi is enabled with SAVE_NOECHO.
|
||||
* pro: If the user has a linemode-only client she is not left in
|
||||
* useless NOECHO mode
|
||||
* con: The NOECHO is delayed by the round trip time for the negotiation
|
||||
* which could be imense on very slow lines.
|
||||
* TODO: Need to defined SAVE_NOECHO in comm.c for this.
|
||||
*/
|
||||
#define CHARMODE_MASK (CHARMODE|CHARMODE_ACK)
|
||||
/* Mask for active charmode states.
|
||||
*/
|
||||
|
||||
/* --- Variables --- */
|
||||
|
||||
extern int num_pending_outconns; /* new! optimization! --lynX 2007 */
|
||||
|
||||
extern Bool sending_telnet_command;
|
||||
extern interactive_t *all_players[MAX_PLAYERS];
|
||||
extern int num_player;
|
||||
extern char *message_flush;
|
||||
extern char *domain_name;
|
||||
|
||||
extern long pthread_write_max_size;
|
||||
|
||||
#ifdef COMM_STAT
|
||||
extern unsigned long add_message_calls;
|
||||
extern unsigned long inet_packets;
|
||||
extern unsigned long inet_volume;
|
||||
extern unsigned long inet_packets_in;
|
||||
extern unsigned long inet_volume_in;
|
||||
#endif
|
||||
|
||||
/* --- Prototypes --- */
|
||||
|
||||
extern void initialize_host_name (const char *hname);
|
||||
extern void initialize_host_ip_number(const char *, const char *);
|
||||
extern void prepare_ipc(void);
|
||||
extern void ipc_remove(void);
|
||||
#ifdef USE_PTHREADS
|
||||
extern void interactive_lock (interactive_t *ip);
|
||||
extern void interactive_unlock (interactive_t *ip);
|
||||
extern void interactive_cleanup (interactive_t *ip);
|
||||
#else
|
||||
extern void interactive_lock (interactive_t *ip UNUSED);
|
||||
extern void interactive_unlock (interactive_t *ip UNUSED);
|
||||
extern void interactive_cleanup (interactive_t *ip UNUSED);
|
||||
#endif /* USE_PTHREADS */
|
||||
extern void comm_cleanup_interactives (void);
|
||||
extern void add_message VARPROT((const char *, ...), printf, 1, 2);
|
||||
extern void flush_all_player_mess(void);
|
||||
extern Bool get_message(char *buff, size_t *len);
|
||||
extern void remove_interactive(object_t *ob, Bool force);
|
||||
extern void set_noecho(interactive_t *i, char noecho, Bool local_change);
|
||||
extern int find_no_bang (interactive_t *ip);
|
||||
extern Bool call_function_interactive(interactive_t *i, char *str, size_t len);
|
||||
extern void remove_all_players(void);
|
||||
extern void print_prompt(void);
|
||||
extern void init_telopts(void);
|
||||
extern void mudlib_telopts(void);
|
||||
extern svalue_t *v_input_to (svalue_t *sp, int num_arg);
|
||||
|
||||
extern svalue_t *f_query_udp_port(svalue_t *sp);
|
||||
|
||||
#ifdef ERQ_DEMON
|
||||
extern void start_erq_demon(const char *suffix, size_t suffixlen);
|
||||
extern svalue_t *f_attach_erq_demon(svalue_t *sp);
|
||||
extern svalue_t *f_send_erq(svalue_t *sp);
|
||||
#endif
|
||||
|
||||
extern size_t show_comm_status (strbuf_t * sbuf, Bool verbose);
|
||||
extern void remove_stale_player_data (void);
|
||||
extern void check_for_out_connections (void);
|
||||
|
||||
#ifdef GC_SUPPORT
|
||||
extern void clear_comm_refs(void);
|
||||
extern void count_comm_refs(void);
|
||||
#endif /* GC_SUPPORT */
|
||||
|
||||
extern char *query_host_name(void);
|
||||
extern char *get_host_ip_number(void);
|
||||
extern svalue_t *f_query_idle(svalue_t *sp);
|
||||
extern svalue_t *f_remove_interactive(svalue_t *sp);
|
||||
|
||||
#ifdef DEBUG
|
||||
extern void count_comm_extra_refs(void);
|
||||
#endif /* DEBUG */
|
||||
|
||||
extern svalue_t *f_send_udp(svalue_t *sp);
|
||||
|
||||
extern svalue_t *f_binary_message(svalue_t *sp);
|
||||
extern svalue_t *f_exec(svalue_t *sp);
|
||||
extern svalue_t *f_interactive(svalue_t *sp);
|
||||
extern svalue_t *f_query_input_pending(svalue_t *sp);
|
||||
extern svalue_t *f_query_ip_name(svalue_t *sp);
|
||||
extern svalue_t *f_query_ip_number(svalue_t *sp);
|
||||
extern svalue_t *f_query_mud_port(svalue_t *sp);
|
||||
extern svalue_t *v_find_input_to (svalue_t *sp, int num_arg);
|
||||
extern svalue_t *v_remove_input_to (svalue_t *sp, int num_arg);
|
||||
extern svalue_t *f_input_to_info (svalue_t *sp);
|
||||
extern svalue_t *f_set_buffer_size(svalue_t *sp);
|
||||
extern svalue_t *f_get_combine_charset(svalue_t *sp);
|
||||
extern svalue_t *f_set_combine_charset(svalue_t *sp);
|
||||
extern svalue_t *f_get_connection_charset(svalue_t *sp);
|
||||
extern svalue_t *f_set_connection_charset(svalue_t *sp);
|
||||
extern svalue_t *f_set_prompt(svalue_t *sp);
|
||||
extern svalue_t *f_users(svalue_t *sp);
|
||||
extern svalue_t *f_get_max_commands (svalue_t *sp);
|
||||
extern svalue_t *f_set_max_commands (svalue_t *sp);
|
||||
extern svalue_t *f_enable_telnet (svalue_t *sp);
|
||||
extern svalue_t *f_net_connect (svalue_t *sp);
|
||||
|
||||
#if defined(ACCESS_CONTROL)
|
||||
extern void refresh_access_data(void (*add_entry)(struct sockaddr_in *, int, long*) );
|
||||
#endif /* ACCESS_CONTROL */
|
||||
|
||||
#ifdef USE_SNOOPING
|
||||
extern svalue_t *f_query_snoop(svalue_t *sp);
|
||||
extern svalue_t *v_snoop(svalue_t *sp, int num_arg);
|
||||
#endif
|
||||
|
||||
#endif /* COMM_H__ */
|
711
src/config.h.in
Normal file
711
src/config.h.in
Normal file
|
@ -0,0 +1,711 @@
|
|||
/* DO NOT EDIT!
|
||||
*
|
||||
* This file is created automatically by configure from the template
|
||||
* in config.h.in.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H__
|
||||
#define CONFIG_H__ 1
|
||||
|
||||
/* ----------- Commandline Argument Defaults ----------
|
||||
* These options provide default settings for those options which can
|
||||
* also be set on the commandline.
|
||||
*/
|
||||
|
||||
|
||||
/* Define COMPAT_MODE if you are using the 2.4.5 mudlib or one of its
|
||||
* derivatives.
|
||||
*/
|
||||
@cdef_compat_mode@ COMPAT_MODE
|
||||
|
||||
/* The name of the master object.
|
||||
*/
|
||||
#define MASTER_NAME @val_master_name@
|
||||
|
||||
/* Define ALLOW_FILENAME_SPACES if the driver should accept space characters
|
||||
* in filenames. If it is not defined, a hardcoded test for space characters
|
||||
* is activated.
|
||||
*/
|
||||
@cdef_filename_spaces@ ALLOW_FILENAME_SPACES
|
||||
|
||||
|
||||
/* --- Runtime limits --- */
|
||||
|
||||
/* This is the maximum array size allowed for one single array.
|
||||
* If 0, any size is allowed.
|
||||
*/
|
||||
#define MAX_ARRAY_SIZE @val_max_array_size@
|
||||
|
||||
/* This is the maximum number of entries allowed for a single mapping.
|
||||
* If 0, any size is allowed.
|
||||
*/
|
||||
#define MAX_MAPPING_KEYS @val_max_mapping_keys@
|
||||
|
||||
/* This is the maximum number of values held in a single mapping.
|
||||
* If 0, any size is allowed.
|
||||
*/
|
||||
#define MAX_MAPPING_SIZE @val_max_mapping_size@
|
||||
|
||||
/* Max size of a file allowed to be read by 'read_file()'.
|
||||
*/
|
||||
#define READ_FILE_MAX_SIZE @val_read_file_max_size@
|
||||
|
||||
/* Define MAX_BYTE_TRANSFER to the number of bytes you allow to be read
|
||||
* and written with read_bytes and write_bytes
|
||||
*/
|
||||
#define MAX_BYTE_TRANSFER @val_max_byte_transfer@
|
||||
|
||||
/* This is the maximum number of callouts allowed at one time.
|
||||
* If 0, any number is allowed.
|
||||
*/
|
||||
#define MAX_CALLOUTS @val_max_callouts@
|
||||
|
||||
/* When USE_PTHREADS is used, define this to the maximum amount of data
|
||||
* to be held pending for writing.
|
||||
* A value of 0 means 'unlimited'.
|
||||
*/
|
||||
#define PTHREAD_WRITE_MAX_SIZE @val_pthreads_write_max_size@
|
||||
|
||||
|
||||
/* --- Timing --- */
|
||||
|
||||
/* If an object is left alone for a certain time, then the
|
||||
* function clean_up will be called. This function can do anything,
|
||||
* like destructing the object. If the function isn't defined by the
|
||||
* object, then nothing will happen.
|
||||
*
|
||||
* This time should be substantially longer than the swapping time.
|
||||
*/
|
||||
#define TIME_TO_CLEAN_UP @val_time_to_clean_up@
|
||||
|
||||
/* How long time until an unused object is swapped out.
|
||||
* Machine with too many players and too little memory: 900 (15 minutes)
|
||||
* Machine with few players and lot of memory: 10000
|
||||
* Machine with infinite memory: 0 (never swap).
|
||||
*/
|
||||
#define TIME_TO_SWAP @val_time_to_swap@
|
||||
#define TIME_TO_SWAP_VARIABLES @val_time_to_swap_variables@
|
||||
|
||||
/* How many seconds until an object is reset again.
|
||||
* Set this value high if big system, otherwise low.
|
||||
*/
|
||||
#define TIME_TO_RESET @val_time_to_reset@
|
||||
|
||||
/* The granularity of alarm() calls.
|
||||
* This is the granularity of the call_outs,
|
||||
* and base granularity of heart_beat, reset und clean_up calls.
|
||||
*/
|
||||
#define ALARM_TIME @val_alarm_time@
|
||||
|
||||
/* The interval between heart beats.
|
||||
*/
|
||||
#define HEART_BEAT_INTERVAL @val_heart_beat_interval@
|
||||
|
||||
/* Shall all heart beats happen in the same time frame?
|
||||
* (i.e. only every HEART_BEAT_INTERVAL seconds.)
|
||||
*/
|
||||
@cdef_synchronous_heart_beat@ SYNCHRONOUS_HEART_BEAT
|
||||
|
||||
/* --- Memory --- */
|
||||
|
||||
/* Reserve an extra memory area from malloc(), to free when we run out
|
||||
* of memory to get some warning and start Armageddon.
|
||||
* If this value is 0, no area will be reserved.
|
||||
*/
|
||||
#define RESERVED_USER_SIZE @val_reserved_user_size@
|
||||
#define RESERVED_MASTER_SIZE @val_reserved_master_size@
|
||||
#define RESERVED_SYSTEM_SIZE @val_reserved_system_size@
|
||||
|
||||
/* If MIN_MALLOCED is > 0, the gamedriver will reserve this amount of
|
||||
* memory on startup for large blocks, thus reducing the large block
|
||||
* fragmentation. The value therefore should be a significantly large
|
||||
* multiple of the large chunk size.
|
||||
* As a rule of thumb, reserve enough memory to cover the first couple
|
||||
* of days of uptime.
|
||||
*/
|
||||
#define MIN_MALLOCED @val_min_malloced@
|
||||
|
||||
/* If MIN_SMALL_MALLOCED is > 0, the gamedriver will reserve this
|
||||
* amount of memory on startup for small blocks, thus reducing the small block
|
||||
* fragmentation. The value therefore should be a significantly large
|
||||
* multiple of the small chunk size.
|
||||
* As a rule of thumb, reserve enough memory to cover the first couple
|
||||
* of days of uptime.
|
||||
*/
|
||||
#define MIN_SMALL_MALLOCED @val_min_small_malloced@
|
||||
|
||||
/* This value gives the upper limit for the total allocated memory
|
||||
* (useful for systems with no functioning process limit).
|
||||
* A value of 0 means 'unlimited'.
|
||||
* TODO: This should be named 'MAX_MALLOC' - ditto in configure.
|
||||
*/
|
||||
#define MAX_MALLOCED @val_max_malloced@
|
||||
|
||||
|
||||
/* --- Interpreter --- */
|
||||
|
||||
/* Define STRICT_EUIDS if the driver is to enforce the use of euids,
|
||||
* ie. load_object() and clone_object() require the current object to
|
||||
* have a non-zero euid.
|
||||
*/
|
||||
@cdef_strict_euids@ STRICT_EUIDS
|
||||
|
||||
/* Maximum number of evaluated nodes/loop.
|
||||
* If this is exceeded, the current function is halted.
|
||||
*/
|
||||
#define MAX_COST @val_max_cost@
|
||||
|
||||
/* Define SHARE_VARIABLES if a clone's variables are to be assigned
|
||||
* from the current blueprint's variables. Undefine it if clones
|
||||
* should be initialized by __INIT().
|
||||
*/
|
||||
@cdef_share_variables@ SHARE_VARIABLES
|
||||
|
||||
|
||||
/* --- Communication --- */
|
||||
|
||||
/* The input escape character.
|
||||
*/
|
||||
#define INPUT_ESCAPE @val_input_escape@
|
||||
|
||||
/* Define what port number the game is to use.
|
||||
*/
|
||||
#define PORTNO @val_portno@
|
||||
|
||||
/* Define this to the port on which the driver can receive UDP message.
|
||||
* If set to -1, the port will not be opened unless the mud is given a valid
|
||||
* port number on startup with the -u commandline option.
|
||||
*/
|
||||
#define UDP_PORT @val_udp_port@
|
||||
|
||||
/* Maximum numbers of ports the GD accepts connections to.
|
||||
*/
|
||||
#define MAXNUMPORTS @val_maxnumports@
|
||||
|
||||
/* Should code for the external request demon be included?
|
||||
*/
|
||||
@cdef_erq_demon@ ERQ_DEMON
|
||||
|
||||
/* Maximum sizes for an erq send or reply.
|
||||
*/
|
||||
#define ERQ_MAX_REPLY @val_erq_max_reply@
|
||||
#define ERQ_MAX_SEND @val_erq_max_send@
|
||||
|
||||
/* Define this if you want IPv6 support (assuming that your host
|
||||
* actually offers this.
|
||||
*/
|
||||
@cdef_use_ipv6@ USE_IPV6
|
||||
|
||||
/* If you want to use threads to write the data to the sockets
|
||||
* define USE_PTHREADS.
|
||||
*/
|
||||
|
||||
@cdef_use_pthreads@ USE_PTHREADS
|
||||
|
||||
|
||||
|
||||
/* ----------- Compilation Options ----------
|
||||
* To change these options, the config.h must be recreated and the
|
||||
* driver recompiled.
|
||||
*/
|
||||
|
||||
/* Trace the most recently executed bytecode instructions?
|
||||
*/
|
||||
@cdef_trace_code@ TRACE_CODE
|
||||
|
||||
/* If using TRACE_CODE , how many instructions should be kept?
|
||||
*/
|
||||
#define TOTAL_TRACE_LENGTH @val_total_trace_length@
|
||||
|
||||
/* Runtime statistics:
|
||||
* COMM_STAT: count number and size of outgoing packets.
|
||||
* APPLY_CACHE_STAT: count number of hits and misses in the apply cache.
|
||||
*/
|
||||
@cdef_comm_stat@ COMM_STAT
|
||||
@cdef_apply_cache_stat@ APPLY_CACHE_STAT
|
||||
|
||||
/* The name of the swapfile used by the driver to swap out objects (if
|
||||
* enabled), relative to the mudlib directory. The driver will append
|
||||
* '.<hostname>' to the file.
|
||||
*/
|
||||
#define SWAP_FILE @val_swap_file@
|
||||
|
||||
|
||||
/* --- Memory --- */
|
||||
|
||||
/* Which memory manager to use. Possible defines are
|
||||
* MALLOC_smalloc: Satoria's malloc. Fastest, uses the least memory,
|
||||
* supports garbage collection.
|
||||
* MALLOC_slaballoc: Slab allocator. Fastest, reduces fragmentation,
|
||||
* supports garbage collection, not threadsafe.
|
||||
* MALLOC_sysmalloc: the normal system malloc()
|
||||
* MALLOC_ptmalloc: ptmalloc from www.malloc.de - threadsafe.
|
||||
*/
|
||||
|
||||
#define MALLOC_@val_malloc@
|
||||
|
||||
/* Define this to let the memory allocator request memory from the system
|
||||
* directly using sbrk() (assuming the system supports it).
|
||||
* If not defined, the memory allocator will use malloc().
|
||||
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
|
||||
*/
|
||||
@cdef_malloc_sbrk@ MALLOC_SBRK
|
||||
|
||||
/* Define this to annotate all allocations with a magic word to find
|
||||
* simple misuses of memory (like multiple frees).
|
||||
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
|
||||
*/
|
||||
@cdef_malloc_check@ MALLOC_CHECK
|
||||
|
||||
/* Define this to annotate all allocations with file:line of the driver
|
||||
* source responsible for it.
|
||||
*/
|
||||
@cdef_malloc_trace@ MALLOC_TRACE
|
||||
|
||||
/* Define this to annotate all allocations with file:line of the lpc program
|
||||
* responsible for it.
|
||||
*/
|
||||
@cdef_malloc_lpc_trace@ MALLOC_LPC_TRACE
|
||||
|
||||
/* Define this to log all calls to esbrk() (the system memory allocator).
|
||||
* Works best if MALLOC_TRACE is defined.
|
||||
* This define is useful if your mud keeps growing in total memory size
|
||||
* instead of re-using the memory already allocated.
|
||||
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
|
||||
*/
|
||||
@cdef_malloc_sbrk_trace@ MALLOC_SBRK_TRACE
|
||||
|
||||
/* --- Wizlist --- */
|
||||
|
||||
/* Where to save the WIZLIST information.
|
||||
* If not defined, and neither given on the commandline, the driver will
|
||||
* not read the WIZLIST file.
|
||||
*/
|
||||
@cdef_wizlist_file@ WIZLIST_FILE @val_wizlist_file@
|
||||
|
||||
|
||||
/* --- Access Control --- */
|
||||
/* #define ACCESS_CONTROL if you want the driver to do any access control.
|
||||
* TODO: Make this a runtime option.
|
||||
*/
|
||||
@cdef_access_control@ ACCESS_CONTROL
|
||||
|
||||
/* file for access permissions data */
|
||||
/* TODO: Make this a runtime option */
|
||||
#define ACCESS_FILE @val_access_file@
|
||||
|
||||
/* logfile to show valid and rejected connections
|
||||
* simple not define this for NO logs
|
||||
* TODO: Make this a runtime option.
|
||||
*/
|
||||
@cdef_access_log@ ACCESS_LOG @val_access_log@
|
||||
|
||||
|
||||
/* --- Language --- */
|
||||
|
||||
/* Define USE_PARSE_COMMAND if you want the efun parse_command().
|
||||
*/
|
||||
@cdef_use_parse_command@ USE_PARSE_COMMAND
|
||||
|
||||
/* Define USE_SET_LIGHT if you want the efun set_light() and the
|
||||
* simple 2.4.5 light system.
|
||||
*/
|
||||
@cdef_use_set_light@ USE_SET_LIGHT
|
||||
|
||||
/* Define USE_SET_IS_WIZARD if you want the efun set_is_wizard().
|
||||
*/
|
||||
@cdef_use_set_is_wizard@ USE_SET_IS_WIZARD
|
||||
|
||||
/* Define USE_PROCESS_STRING if you want the efun process_string().
|
||||
*/
|
||||
@cdef_use_process_string@ USE_PROCESS_STRING
|
||||
|
||||
/* Define USE_SYSTEM_CRYPT if you want crypt() to be implemented by your
|
||||
* operating system (assuming it offers this function). This makes your
|
||||
* programm smaller and may even let you take advantage of improvements
|
||||
* of your OS, but may also prohibit transporting encrypted date like
|
||||
* passwords between different systems.
|
||||
* Undefine USE_SYSTEM_CRYPT if you want to use the driver's portable
|
||||
* crypt() implementation.
|
||||
*/
|
||||
@cdef_use_system_crypt@ USE_SYSTEM_CRYPT
|
||||
|
||||
/* Define this if you want MCCP (Mud Control Compression Protocol).
|
||||
*/
|
||||
@cdef_use_mccp@ USE_MCCP
|
||||
|
||||
/* Define this if you want TLS (Transport Layer Security) over Telnet.
|
||||
*/
|
||||
@cdef_use_tls@ USE_TLS
|
||||
|
||||
/* Define this if you want mySQL support (assuming that your host
|
||||
* actually offers this.
|
||||
*/
|
||||
@cdef_use_mysql@ USE_MYSQL
|
||||
|
||||
/* Define this if you want PostgreSQL support (assuming that your host
|
||||
* actually offers this.
|
||||
*/
|
||||
@cdef_use_pgsql@ USE_PGSQL
|
||||
|
||||
/* Define this if you want SQLite support (assuming that your host
|
||||
* actually offers this.
|
||||
*/
|
||||
@cdef_use_sqlite@ USE_SQLITE
|
||||
|
||||
/* Define this if you want JSON support (assuming that your host
|
||||
* actually offers this.
|
||||
*/
|
||||
@cdef_use_json@ USE_JSON
|
||||
|
||||
/* Define this if you want expat support (assuming that your host
|
||||
* actually offers this.
|
||||
*/
|
||||
@cdef_use_expat@ USE_EXPAT
|
||||
|
||||
/* Define this if you want alist support.
|
||||
*/
|
||||
@cdef_use_alists@ USE_ALISTS
|
||||
|
||||
/* Define this if you want to allow call_other()s on arrays of objects.
|
||||
*/
|
||||
@cdef_lpc_array_calls@ USE_ARRAY_CALLS
|
||||
|
||||
/* Define this if you want PCRE instead of traditional regexps.
|
||||
*/
|
||||
@cdef_use_pcre@ USE_PCRE
|
||||
|
||||
/* Define this if you want to use builtin PCRE (ignored when PCRE
|
||||
* is disabled as a whole).
|
||||
*/
|
||||
@cdef_use_builtin_pcre@ USE_BUILTIN_PCRE
|
||||
|
||||
/* Define this if you want the obsolete and deprecated efuns.
|
||||
*/
|
||||
@cdef_use_deprecated@ USE_DEPRECATED
|
||||
|
||||
|
||||
/* --- Runtime limits --- */
|
||||
|
||||
/* Maximum size of a socket send buffer.
|
||||
*/
|
||||
#define SET_BUFFER_SIZE_MAX @val_set_buffer_size_max@
|
||||
|
||||
/* CATCH_RESERVED_COST is the default value added to the eval cost for the
|
||||
* time executing code guarded by a catch() statement, so that an
|
||||
* eval_cost-too-big error can still be caught and handled.
|
||||
*
|
||||
* To catch an eval_cost too big error in an object that called recursive
|
||||
* master functions, CATCH_RESERVED_COST should be greater than
|
||||
* MASTER_RESERVED_COST.
|
||||
*/
|
||||
#define CATCH_RESERVED_COST @val_catch_reserved_cost@
|
||||
|
||||
/* MASTER_RESERVED_COST is the total reserve available for master applies.
|
||||
* It is halved for every recursion into another master apply.
|
||||
*/
|
||||
#define MASTER_RESERVED_COST @val_master_reserved_cost@ /* must be power of 2 */
|
||||
/* TODO: Check that at runtime */
|
||||
|
||||
/* If this is defined, expensive operations like string additions
|
||||
* receive additional evalcosts depending on the amount of data handled.
|
||||
*/
|
||||
@cdef_dynamic_costs@ DYNAMIC_COSTS
|
||||
|
||||
/* Define the maximum stack size of the stack machine. This stack will also
|
||||
* contain all local variables and arguments.
|
||||
*/
|
||||
#define EVALUATOR_STACK_SIZE @val_evaluator_stack_size@
|
||||
|
||||
/* Define the maximum call depth for functions.
|
||||
* MAX_USER_TRACE is used for for normal program execution, the full
|
||||
* MAX_TRACE is only available in error handling.
|
||||
*
|
||||
* MAX_TRACE must be larger than MAX_USER_TRACE (check at compile time).
|
||||
*/
|
||||
#define MAX_USER_TRACE @val_max_user_trace@
|
||||
#define MAX_TRACE @val_max_trace@
|
||||
|
||||
/* Maximum number of bits in a bit field. They are stored in printable
|
||||
* strings, 6 bits per byte.
|
||||
* The limit is more based on considerations of speed than memory
|
||||
* consumption.
|
||||
*/
|
||||
#define MAX_BITS @val_max_bits@
|
||||
|
||||
/* Maximum number of players in the game.
|
||||
*/
|
||||
#define MAX_PLAYERS @val_max_players@
|
||||
|
||||
/* When uploading files, we want fast response; however, normal players
|
||||
* shouldn't be able to hog the system in this way. Define ALLOWED_ED_CMDS
|
||||
* to be the ratio of the no of ed cmds executed per player cmd.
|
||||
*/
|
||||
#define ALLOWED_ED_CMDS @val_allowed_ed_cmds@
|
||||
/* TODO: ALLOWED_ED_CMDS: make this a runtime option */
|
||||
|
||||
|
||||
/* --- Compiler --- */
|
||||
|
||||
/* Define the size of the compiler stack. This defines how complex
|
||||
* expressions the compiler can parse. The value should be big enough.
|
||||
*/
|
||||
#define COMPILER_STACK_SIZE @val_compiler_stack_size@
|
||||
|
||||
/* Max number of local variables in a function.
|
||||
*/
|
||||
#define MAX_LOCAL @val_max_local@
|
||||
|
||||
/* Maximum size of an expanded preprocessor definition.
|
||||
*/
|
||||
#define DEFMAX @val_defmax@
|
||||
|
||||
|
||||
/* --- Internal Tables --- */
|
||||
|
||||
/* Define the size of the shared string hash table. This number needn't
|
||||
* be prime, probably between 1000 and 30000; if you set it to about 1/5
|
||||
* of the number of distinct strings you have, you will get a hit ratio
|
||||
* (number of comparisons to find a string) very close to 1, as found strings
|
||||
* are automatically moved to the head of a hash chain. You will never
|
||||
* need more, and you will still get good results with a smaller table.
|
||||
* If the size is a power of two, hashing will be faster.
|
||||
*/
|
||||
#define HTABLE_SIZE @val_htable_size@
|
||||
|
||||
/* Object hash table size.
|
||||
* Define this like you did with the strings; probably set to about 1/4 of
|
||||
* the number of objects in a game, as the distribution of accesses to
|
||||
* objects is somewhat more uniform than that of strings.
|
||||
*/
|
||||
#define OTABLE_SIZE @val_otable_size@
|
||||
|
||||
/* Define the size of the table of defines, reserved words, identifiers
|
||||
* and efun names. Should be either several times smaller than HTABLE_SIZE
|
||||
* or identical with it.
|
||||
*/
|
||||
#define ITABLE_SIZE @val_itable_size@
|
||||
|
||||
/* the number of apply_low cache entries will be 2^APPLY_CACHE_BITS.
|
||||
*/
|
||||
#define APPLY_CACHE_BITS @val_apply_cache_bits@
|
||||
|
||||
/* The parameters of the regular expression/result cache.
|
||||
* The expression cache uses a hashtable of RXCACHE_TABLE entries.
|
||||
* Undefine RXCACHE_TABLE to disable the all regexp caching.
|
||||
*/
|
||||
@cdef_rxcache_table@ RXCACHE_TABLE @val_rxcache_table@
|
||||
|
||||
/* --- Current Developments ---
|
||||
* These options can be used to disable developments-in-progress if their
|
||||
* code turns out to be interrrupting.
|
||||
*/
|
||||
|
||||
/* Define this if you want structs supported.
|
||||
*/
|
||||
@cdef_use_structs@ USE_STRUCTS
|
||||
|
||||
/* Define this if you want the new inline closure syntax supported.
|
||||
* (f-020528).
|
||||
*/
|
||||
@cdef_use_new_inlines@ USE_NEW_INLINES
|
||||
|
||||
|
||||
/* --- Profiling ---
|
||||
* For profiling of the VM instruction implementations, refer to the Makefile
|
||||
*/
|
||||
|
||||
/* Enable usage statistics of VM instructions.
|
||||
* For profiling of the VM instructions themselves, see the Profiling
|
||||
* Options in the Makefile.
|
||||
*/
|
||||
@cdef_opcprof@ OPCPROF
|
||||
|
||||
#ifdef OPCPROF
|
||||
/* With OPCPROF, the dump of the statistics include the names
|
||||
* of the instructions.
|
||||
*/
|
||||
@cdef_verbose_opcprof@ VERBOSE_OPCPROF
|
||||
#endif
|
||||
|
||||
|
||||
/* --- Standard Debugging --- */
|
||||
|
||||
/* Enable basic run time sanity checks. This will use more time
|
||||
* and space, but nevertheless you are strongly encouraged to keep
|
||||
* it defined.
|
||||
*/
|
||||
@cdef_debug@ DEBUG
|
||||
|
||||
/* Enable debug output from the LPC compiler.
|
||||
*/
|
||||
@cdef_yydebug@ YYDEBUG
|
||||
|
||||
/* Disable inlining.
|
||||
*/
|
||||
@cdef_no_inlines@ NO_INLINES
|
||||
|
||||
/* Activate debug prints in the telnet machine.
|
||||
*/
|
||||
@cdef_debug_telnet@ DEBUG_TELNET
|
||||
|
||||
/* Activate allocation debug prints in the malloc module.
|
||||
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
|
||||
*/
|
||||
@cdef_debug_malloc_allocs@ DEBUG_MALLOC_ALLOCS
|
||||
|
||||
/* The DEBUG level for the ERQ daemon:
|
||||
* 0 : no debug output
|
||||
* 1 : standard debug output
|
||||
* 2 : verbose debug output
|
||||
*/
|
||||
#define ERQ_DEBUG @val_erq_debug@
|
||||
|
||||
/* --- Specific Debugging ---
|
||||
* These options have been introduced to debug specific problems and will
|
||||
* be removed again later.
|
||||
*/
|
||||
|
||||
/* Enable the automatic data cleanup from the backend.
|
||||
* TODO: Remove this macro once it is proven stable.
|
||||
*/
|
||||
#define NEW_CLEANUP
|
||||
|
||||
/* Log the details of the automatic data cleanup for each individual object.
|
||||
* This is useful if the cleanup is suspected to hog the CPU.
|
||||
* TODO: Remove this macro once it is proven stable.
|
||||
*/
|
||||
#undef LOG_NEW_CLEANUP
|
||||
|
||||
/* Log the details of the automatic data cleanup of all objects. This is
|
||||
* useful if the cleanup is suspected to hog the CPU.
|
||||
* TODO: Remove this macro once it is proven stable.
|
||||
*/
|
||||
#define LOG_NEW_CLEANUP_ALL
|
||||
|
||||
/* Enable the use of freelists in the malloc AVL nodes.
|
||||
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
|
||||
* TODO: Remove this macro once it is proven stable or if the change
|
||||
* TODO:: didn't bring any advantages..
|
||||
*/
|
||||
#define USE_AVL_FREELIST
|
||||
|
||||
/* Order malloc large block freelists by address.
|
||||
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
|
||||
* TODO: Remove if it doesn't help with the fragmentation, as it uses up
|
||||
* TODO:: a small, but measurable amount of time in the allocator.
|
||||
*/
|
||||
#define MALLOC_ORDER_LARGE_FREELISTS
|
||||
|
||||
/* Order slaballoc partial-slab freelists by number of free blocks.
|
||||
* Supported by: MALLOC_slaballoc.
|
||||
* TODO: Remove if it doesn't help with the fragmentation, as it uses up
|
||||
* TODO:: a small, but measurable amount of time in the allocator.
|
||||
*/
|
||||
#define MALLOC_ORDER_SLAB_FREELISTS
|
||||
|
||||
/* Allow slaballoc to use multiples of DESIRED_SLAB_SIZE when creating
|
||||
* new slabs.
|
||||
*/
|
||||
#define SLABALLOC_DYNAMIC_SLABS
|
||||
|
||||
/* Collect extended malloc statistics.
|
||||
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
|
||||
* TODO: Remove this macro or make it configurable.
|
||||
*/
|
||||
#define MALLOC_EXT_STATISTICS
|
||||
|
||||
/* Collected statistics about string comparisons.
|
||||
* TODO: Remove this macro after we got our data.
|
||||
*/
|
||||
#define EXT_STRING_STATS
|
||||
|
||||
/* Trace changes to the tot_alloc_object and tot_alloc_object_size
|
||||
* statistics, in order to find the status bugs (enables commandline
|
||||
* option --check-object-stat). Will produce a decent amount of
|
||||
* output on stderr.
|
||||
*/
|
||||
@cdef_check_object_stat@ CHECK_OBJECT_STAT
|
||||
|
||||
/* Activate total mapping size consistency check code. It has a small
|
||||
* impact on the execution speed. This define was used to find
|
||||
* the inaccuracy in the mapping statistic.
|
||||
*/
|
||||
@cdef_check_mapping_total@ CHECK_MAPPING_TOTAL
|
||||
|
||||
/* Activate object refcount check code. It will produce a decent
|
||||
* amount of log output. It will also fatal() the driver as soon
|
||||
* as it detects an inconsistency in the list of destructed objects.
|
||||
*/
|
||||
@cdef_check_object_ref@ CHECK_OBJECT_REF
|
||||
|
||||
/* Activate object referencing checking code during the GC. It will
|
||||
* print error messages to gcout when an object or program is
|
||||
* referenced as something else. No penalty for using.
|
||||
* Requires MALLOC_TRACE to work. Incompatible with DUMP_GC_REFS.
|
||||
*/
|
||||
#ifdef MALLOC_TRACE
|
||||
@cdef_check_object_gc_ref@ CHECK_OBJECT_GC_REF
|
||||
#endif
|
||||
|
||||
/* Sometimes the GC stumbles over invalid references to memory
|
||||
* blocks (namely 'Program referenced as something else'). Define
|
||||
* this macro to get a detailed dump of all found references
|
||||
* (Warning: LOTS of output!). Incompatible with CHECK_OBJECT_GC_REF.
|
||||
*/
|
||||
@cdef_dump_gc_refs@ DUMP_GC_REFS
|
||||
|
||||
|
||||
|
||||
/****** PSYCLPC ******/
|
||||
|
||||
/* maximum number of currently outgoing connections which are
|
||||
* not yet fully established
|
||||
* psyced needs a quite large value here
|
||||
*/
|
||||
#define MAX_OUTCONN @val_max_net_connects@
|
||||
|
||||
/* Size of each interactive socket's buffer for incoming data.
|
||||
* This is also the maximum size for one command().
|
||||
* For MUD use, this value used to be 2048 traditionally.
|
||||
*/
|
||||
#define MAX_TEXT @val_size_socket_buffer@
|
||||
|
||||
/* Why make comments in config.h if you're not supposed to edit it anyway?
|
||||
* Here is the list of the new psyclpc flags.
|
||||
* See elsewhere for explainations.
|
||||
*
|
||||
@cdef_backtrace_always@ BACKTRACE_ALWAYS
|
||||
@cdef_use_paranoid_refs@ PARANOID_REFS
|
||||
*/
|
||||
@cdef_use_actions@ USE_ACTIONS
|
||||
@cdef_use_authlocal@ USE_AUTHLOCAL
|
||||
@cdef_use_builtin_editor@ USE_BUILTIN_EDITOR
|
||||
@cdef_use_experimental@ USE_EXPERIMENTAL
|
||||
@cdef_use_inventories@ USE_INVENTORIES
|
||||
@cdef_use_ldmud_compatibility@ USE_LDMUD_COMPATIBILITY
|
||||
@cdef_use_paranoia@ USE_PARANOIA
|
||||
@cdef_use_restored_objects@ USE_RESTORED_OBJECTS
|
||||
@cdef_use_shadowing@ USE_SHADOWING
|
||||
@cdef_use_snooping@ USE_SNOOPING
|
||||
@cdef_use_socket_limits@ USE_SOCKET_LIMITS
|
||||
@cdef_use_srv@ USE_SRV
|
||||
@cdef_use_swap@ USE_SWAP
|
||||
|
||||
/* Set up a configuration like LDMUD with a lot more debugging
|
||||
* code in your regularely running driver than you will want.
|
||||
* Of course you also have to set all the new use_something
|
||||
* selectors to yes, or simply run ./configure as it stands.
|
||||
*/
|
||||
#ifdef USE_LDMUD_COMPATIBILITY
|
||||
# ifdef DEBUG
|
||||
# ifndef USE_PARANOIA
|
||||
# define USE_PARANOIA
|
||||
# endif
|
||||
# endif
|
||||
# define CHECK_REFS
|
||||
# define USE_TRASH
|
||||
# define VERBOSE
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_H__ */
|
20134
src/configure
vendored
Executable file
20134
src/configure
vendored
Executable file
File diff suppressed because it is too large
Load diff
39
src/contrib/empty-mapping-check-fix.patch
Normal file
39
src/contrib/empty-mapping-check-fix.patch
Normal file
|
@ -0,0 +1,39 @@
|
|||
# http://mantis.bearnip.com/view.php?id=475
|
||||
|
||||
Consider this code:
|
||||
|
||||
mixed x = m_allocate(100,2); x += ([2:3;4;5]);
|
||||
mixed y = m_allocate(100,2); y = y + ([2:3;4;5]);
|
||||
|
||||
The first line results in an error, saying the mapping width doesn't match. The second line results in y containing mapping of width 3. As x is empty, the first line should work as well.
|
||||
|
||||
add_to_mapping() in mapping.c tests for empty mappings with
|
||||
0 == m2->num_entries && NULL == m2->hash
|
||||
For m_allocate-d mappings, hash is empty but not 0.
|
||||
|
||||
Why is the hash tested at all? 3.2 doesn't have that check.
|
||||
|
||||
Attachment: patch to remove the NULL == m[1,2]->hash tests
|
||||
|
||||
Index: mapping.c
|
||||
===================================================================
|
||||
--- mapping.c (revision 2306)
|
||||
+++ mapping.c (working copy)
|
||||
@@ -3352,7 +3352,7 @@
|
||||
/* If one of the two mappings is empty, we can adjust its width
|
||||
* after getting rid of all pending data blocks.
|
||||
*/
|
||||
- if (0 == m2->num_entries && NULL == m2->hash)
|
||||
+ if (0 == m2->num_entries)
|
||||
{
|
||||
if (m2->cond != NULL)
|
||||
{
|
||||
@@ -3363,7 +3363,7 @@
|
||||
}
|
||||
m2->num_values = m1->num_values;
|
||||
}
|
||||
- else if (0 == m1->num_entries && NULL == m1->hash)
|
||||
+ else if (0 == m1->num_entries)
|
||||
{
|
||||
if (m1->cond != NULL)
|
||||
{
|
80
src/contrib/find_object.patch
Normal file
80
src/contrib/find_object.patch
Normal file
|
@ -0,0 +1,80 @@
|
|||
# http://mantis.bearnip.com/view.php?id=500
|
||||
#
|
||||
diff -ur ldmud-3.3.714/src/mstrings.c ldmud-3.3.714-zesstra/src/mstrings.c
|
||||
--- ldmud-3.3.714/src/mstrings.c 2006-07-10 04:43:25.000000000 +0200
|
||||
+++ ldmud-3.3.714-zesstra/src/mstrings.c 2007-02-25 15:56:17.000000000 +0100
|
||||
@@ -179,22 +179,16 @@
|
||||
#endif /* EXT_STRING_STATS */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
-static INLINE whash_t
|
||||
+/*
|
||||
+whash_t
|
||||
hash_string (const char * const s, size_t size)
|
||||
-
|
||||
-/* Compute the hash for string <s> of length <size> and return it.
|
||||
+ * Compute the hash for string <s> of length <size> and return it.
|
||||
* The result will always be non-zero.
|
||||
+ * NOTE: The definition of the function is now in mstrings.h because it is
|
||||
+ * also used in otable.c and the definition needs to be in every compilation
|
||||
+ * unit which uses it.
|
||||
*/
|
||||
|
||||
-{
|
||||
- whash_t hash;
|
||||
-
|
||||
- hash = whashmem(s, size, MSTRING_HASH_LENGTH);
|
||||
- if (!hash)
|
||||
- hash = 1 << (sizeof (hash) * CHAR_BIT - 1);
|
||||
- return hash;
|
||||
-} /* hash_string() */
|
||||
-
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static INLINE whash_t
|
||||
get_hash (string_t * pStr)
|
||||
diff -ur ldmud-3.3.714/src/mstrings.h ldmud-3.3.714-zesstra/src/mstrings.h
|
||||
--- ldmud-3.3.714/src/mstrings.h 2006-07-10 04:43:26.000000000 +0200
|
||||
+++ ldmud-3.3.714-zesstra/src/mstrings.h 2007-02-25 15:52:32.000000000 +0100
|
||||
@@ -117,6 +117,26 @@
|
||||
|
||||
/* --- Inline functions and macros --- */
|
||||
|
||||
+/*-------------------------------------------------------------------------*/
|
||||
+static INLINE whash_t
|
||||
+hash_string (const char * const s, size_t size)
|
||||
+/* Compute the hash for string <s> of length <size> and return it.
|
||||
+ * The result will always be non-zero.
|
||||
+ * Needs to be in mstrings.h to be inlined because otable.c also uses it.
|
||||
+ * NOTE: it is static so the compiler generates inline functions only visible
|
||||
+ * in the compilation unit. Thus the linker does not bail out in case the
|
||||
+ * compiler does not inline it and it is portable on systems not supporting inline.
|
||||
+ */
|
||||
+{
|
||||
+ whash_t hash;
|
||||
+
|
||||
+ hash = whashmem(s, size, MSTRING_HASH_LENGTH);
|
||||
+ if (!hash)
|
||||
+ hash = 1 << (sizeof (hash) * CHAR_BIT - 1);
|
||||
+ return hash;
|
||||
+} /* hash_string() */
|
||||
+/*-------------------------------------------------------------------------*/
|
||||
+
|
||||
#define mstr_mem_size(s) \
|
||||
(sizeof(string_t) + (s)->size)
|
||||
|
||||
diff -ur ldmud-3.3.714/src/otable.c ldmud-3.3.714-zesstra/src/otable.c
|
||||
--- ldmud-3.3.714/src/otable.c 2006-07-10 04:42:56.000000000 +0200
|
||||
+++ ldmud-3.3.714-zesstra/src/otable.c 2007-02-25 16:12:12.000000000 +0100
|
||||
@@ -51,10 +51,10 @@
|
||||
|
||||
#if !( (OTABLE_SIZE) & (OTABLE_SIZE)-1 )
|
||||
# define ObjHash(s) (mstr_get_hash(s) & ((OTABLE_SIZE)-1) )
|
||||
-# define ObjHashStr(s,len) (whashmem(s, len, MSTRING_HASH_LENGTH) & ((OTABLE_SIZE)-1) )
|
||||
+# define ObjHashStr(s,len) (hash_string(s, len) & ((OTABLE_SIZE)-1) )
|
||||
#else
|
||||
# define ObjHash(s) (mstr_get_hash(s) % OTABLE_SIZE)
|
||||
-# define ObjHashStr(s,len) (whashmem(s, len, MSTRING_HASH_LENGTH) % OTABLE_SIZE)
|
||||
+# define ObjHashStr(s,len) (hash_string(s, len) % OTABLE_SIZE)
|
||||
#endif
|
||||
/* Hash the string <s> and compute the appropriate table index
|
||||
*/
|
105
src/contrib/get_eval_number.patch
Normal file
105
src/contrib/get_eval_number.patch
Normal file
|
@ -0,0 +1,105 @@
|
|||
# http://mantis.bearnip.com/view.php?id=477
|
||||
#
|
||||
# another fine contribution by fufu. requires 'improve-statistics.patch'
|
||||
|
||||
int get_eval_number()
|
||||
Return the current evaluation number. It's incremented for each top-level call. [...]
|
||||
|
||||
The intended purpose of this function is to find out if something has already been done for the current command, heart_beat, call_out or whatever. Control flow in mudlibs is often complicated and adding the necessary infrastructure to a mudlib to answer this question is error-prone and tedious. In the driver it's just a few lines of code.
|
||||
|
||||
Index: doc/efun/get_eval_number
|
||||
===================================================================
|
||||
--- doc/efun/get_eval_number (revision 0)
|
||||
+++ doc/efun/get_eval_number (revision 0)
|
||||
@@ -0,0 +1,17 @@
|
||||
+SYNOPSIS
|
||||
+ int get_eval_number()
|
||||
+
|
||||
+DESCRIPTION
|
||||
+ Return the current evaluation number. It's incremented for each
|
||||
+ top-level call. These are: commands, calls to heart_beat, reset,
|
||||
+ or clean_up, and calls generated by call_out or input_to, master
|
||||
+ applies triggered by external events, send_erq callbacks and the
|
||||
+ calls to logon on player login.
|
||||
+
|
||||
+ The counter is a 32 bits counter so it can overflow occasionally.
|
||||
+
|
||||
+HISTORY
|
||||
+ Since ldmud 3.3.372
|
||||
+
|
||||
+SEE ALSO
|
||||
+ get_eval_cost()
|
||||
Index: src/efuns.c
|
||||
===================================================================
|
||||
--- src/efuns.c (revision 2306)
|
||||
+++ src/efuns.c (working copy)
|
||||
@@ -8702,5 +8702,23 @@
|
||||
return sp;
|
||||
} /* f_utime() */
|
||||
|
||||
+/*-------------------------------------------------------------------------*/
|
||||
+svalue_t *
|
||||
+f_get_eval_number (svalue_t *sp)
|
||||
+
|
||||
+/* EFUN get_eval_number()
|
||||
+ *
|
||||
+ * Return the current evaluation number. It's incremented for each
|
||||
+ * top-level call. These are: commands, calls to heart_beat, reset,
|
||||
+ * or clean_up, and calls generated by call_out or input_to.
|
||||
+ *
|
||||
+ * The counter is a 32 bits counter so it will overflow occasionally.
|
||||
+ */
|
||||
+
|
||||
+{
|
||||
+ push_number(sp, eval_number);
|
||||
+ return sp;
|
||||
+} /* f_get_eval_number */
|
||||
+
|
||||
/***************************************************************************/
|
||||
|
||||
Index: src/func_spec
|
||||
===================================================================
|
||||
--- src/func_spec (revision 2306)
|
||||
+++ src/func_spec (working copy)
|
||||
@@ -772,6 +772,7 @@
|
||||
int set_is_wizard(object, int default: F_CONST1);
|
||||
#endif
|
||||
|
||||
+int get_eval_number();
|
||||
|
||||
/* Obsolete and deprecated functions */
|
||||
|
||||
Index: src/interpret.c
|
||||
===================================================================
|
||||
--- src/interpret.c (revision 2306)
|
||||
+++ src/interpret.c (working copy)
|
||||
@@ -697,7 +697,8 @@
|
||||
|
||||
#endif
|
||||
|
||||
- unsigned long total_evalcost;
|
||||
+unsigned long eval_number; /* evaluation number. 32 bits - will overflow */
|
||||
+unsigned long total_evalcost;
|
||||
static struct timeval eval_begin;
|
||||
/* Current total evalcost counter, and start of the evaluation.
|
||||
*/
|
||||
@@ -772,6 +773,7 @@
|
||||
*/
|
||||
|
||||
{
|
||||
+ eval_number++;
|
||||
total_evalcost = 0;
|
||||
if (gettimeofday(&eval_begin, NULL))
|
||||
{
|
||||
Index: src/interpret.h
|
||||
===================================================================
|
||||
--- src/interpret.h (revision 2306)
|
||||
+++ src/interpret.h (working copy)
|
||||
@@ -116,6 +116,7 @@
|
||||
extern p_int apply_cache_miss;
|
||||
#endif
|
||||
|
||||
+extern unsigned long eval_number;
|
||||
extern unsigned long total_evalcost;
|
||||
extern unsigned long last_total_evalcost;
|
||||
extern struct timeval last_eval_duration;
|
81
src/contrib/improve-statistics.patch
Executable file
81
src/contrib/improve-statistics.patch
Executable file
|
@ -0,0 +1,81 @@
|
|||
# see also http://mantis.bearnip.com/view.php?id=476
|
||||
|
||||
This patch adds calls to mark_start_evaluation() and mark_end_evaluation() for external master applies, calls to logon() and erq_send callbacks. It also adds a mark_end_evaluation() in the global error handler
|
||||
|
||||
there are some other places which may or may not be toplevel evaluations:
|
||||
telnet negotiation hook - I don't know which of the calls are toplevel and which might be triggered while executing code (say, by input_to)
|
||||
noecho hook - same.
|
||||
erq stop hook - called by attach_erq_demon, is it also called at the top level?
|
||||
tls callbacks - didn't look further
|
||||
|
||||
Index: object.c
|
||||
===================================================================
|
||||
--- object.c (revision 2306)
|
||||
+++ object.c (working copy)
|
||||
@@ -921,12 +921,14 @@
|
||||
object_t *save = current_object;
|
||||
|
||||
current_object = ob;
|
||||
+ mark_start_evaluation();
|
||||
ret = apply(STR_LOGON, ob, 0);
|
||||
if (ret == 0)
|
||||
{
|
||||
errorf("Could not find %s() on the player %s\n", get_txt(STR_LOGON), get_txt(ob->name));
|
||||
/* NOTREACHED */
|
||||
}
|
||||
+ mark_end_evaluation();
|
||||
current_object = save;
|
||||
} /* logon_object() */
|
||||
|
||||
Index: comm.c
|
||||
===================================================================
|
||||
--- comm.c (revision 2306)
|
||||
+++ comm.c (working copy)
|
||||
@@ -2860,8 +2860,10 @@
|
||||
assigned_eval_cost = eval_cost = user->call_out_cost;
|
||||
}
|
||||
RESET_LIMITS;
|
||||
+ mark_start_evaluation();
|
||||
secure_callback_lambda(erqp, num_arg);
|
||||
user->call_out_cost = eval_cost;
|
||||
+ mark_end_evaluation();
|
||||
if (!keep_handle || (ob->flags & O_DESTRUCTED))
|
||||
{
|
||||
free_svalue(erqp);
|
||||
Index: backend.c
|
||||
===================================================================
|
||||
--- backend.c (revision 2306)
|
||||
+++ backend.c (working copy)
|
||||
@@ -449,6 +449,7 @@
|
||||
/*
|
||||
* We come here after errors, and have to clear some global variables.
|
||||
*/
|
||||
+ mark_end_evaluation();
|
||||
clear_state();
|
||||
flush_all_player_mess();
|
||||
prevent_object_cleanup = MY_FALSE;
|
||||
Index: interpret.c
|
||||
===================================================================
|
||||
--- interpret.c (revision 2306)
|
||||
+++ interpret.c (working copy)
|
||||
@@ -17334,6 +17334,8 @@
|
||||
save_csp = csp;
|
||||
if (setjmp(error_recovery_info.con.text))
|
||||
{
|
||||
+ if (external)
|
||||
+ mark_end_evaluation();
|
||||
secure_apply_error(save_sp - num_arg, save_csp, external);
|
||||
printf("%s Error in master_ob->%s()\n", time_stamp(), get_txt(fun));
|
||||
debug_message("%s Error in master_ob->%s()\n", time_stamp(), get_txt(fun));
|
||||
@@ -17341,7 +17343,11 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
+ if (external)
|
||||
+ mark_start_evaluation();
|
||||
result = sapply_int(fun, master_ob, num_arg, MY_TRUE, MY_FALSE);
|
||||
+ if (external)
|
||||
+ mark_end_evaluation();
|
||||
}
|
||||
|
||||
/* Free the reserve if we used it */
|
27
src/contrib/load_object.patch
Normal file
27
src/contrib/load_object.patch
Normal file
|
@ -0,0 +1,27 @@
|
|||
# http://mantis.bearnip.com/view.php?id=500
|
||||
#
|
||||
diff -ur ldmud-3.3.714/src/simulate.c ldmud-3.3.714-zesstra/src/simulate.c
|
||||
--- ldmud-3.3.714/src/simulate.c 2006-07-10 04:42:06.000000000 +0200
|
||||
+++ ldmud-3.3.714-zesstra/src/simulate.c 2007-02-25 16:15:09.000000000 +0100
|
||||
@@ -1762,6 +1762,13 @@
|
||||
if ('/' == lname[0])
|
||||
fatal("Improper filename '%s' passed to load_object()\n", lname);
|
||||
#endif
|
||||
+
|
||||
+ // empty lnames may lead to a driver crash in enter_object_hash() if there
|
||||
+ // exists a file '.c' in the root of the mudlib.
|
||||
+ if ((name_length=strlen(lname)) <= 1) {
|
||||
+ load_object_error("Illegal file to load (empty filename)", lname, chain);
|
||||
+ /* NOTREACHED */
|
||||
+ }
|
||||
|
||||
/* It could be that the passed filename is one of an already loaded
|
||||
* object. In that case, simply return that object.
|
||||
@@ -1776,7 +1783,6 @@
|
||||
* the second because lname might be a buffer which is deleted
|
||||
* during the compilation process.
|
||||
*/
|
||||
- name_length = strlen(lname);
|
||||
name = alloca(name_length+2);
|
||||
fname = alloca(name_length+4);
|
||||
if (!name || !fname)
|
12
src/contrib/zesstra-foreach.patch
Normal file
12
src/contrib/zesstra-foreach.patch
Normal file
|
@ -0,0 +1,12 @@
|
|||
# http://mantis.bearnip.com/view.php?id=503
|
||||
--- ldmud-3.3.714.orig/src/interpret.c 2006-07-10 04:44:33.000000000 +0200
|
||||
+++ ldmud-3.3.714/src/interpret.c 2007-04-29 23:55:34.000000000 +0200
|
||||
@@ -15165,6 +15165,8 @@
|
||||
if (arg->type == T_NUMBER)
|
||||
{
|
||||
count = arg->u.number;
|
||||
+ if (count<0 && !use_range)
|
||||
+ ERRORF(("foreach() got %ld, expected a positive integer.\n",count));
|
||||
vars_required = 1;
|
||||
}
|
||||
else if (arg->type == T_STRING)
|
169
src/driver.h
Normal file
169
src/driver.h
Normal file
|
@ -0,0 +1,169 @@
|
|||
#ifndef DRIVER_H__
|
||||
#define DRIVER_H__
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
* Global mandatory include file.
|
||||
*
|
||||
* It contains various global macros and declarations, and takes
|
||||
* care of the proper inclusion of the configuration/portability
|
||||
* include files.
|
||||
*------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define __DRIVER_SOURCE__
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* TODO: Some TODO defines */
|
||||
|
||||
/* NO_NEGATIVE_RANGES: If defined, assignments to negative ranges
|
||||
* like [4..2] are not allowed. However, they are useful at times
|
||||
* and so this switch should be under control of a pragma or special
|
||||
* syntactic construct. For now and for compatibility reasons, these
|
||||
* ranges remain allowed.
|
||||
*/
|
||||
/* #undef NO_NEGATIVE_RANGES */
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
/* Verify some of the definitions in config.h */
|
||||
|
||||
/* Make sure that YYDEBUG is defined to 1 - just being defined
|
||||
* is not sufficient.
|
||||
*/
|
||||
#if defined(YYDEBUG)
|
||||
# undef YYDEBUG
|
||||
# define YYDEBUG 1
|
||||
#endif
|
||||
|
||||
#if !defined(MALLOC_smalloc) && !defined(MALLOC_sysmalloc) && !defined(MALLOC_ptmalloc) && ~defined(MALLOC_slaballoc)
|
||||
# define MALLOC_slaballoc
|
||||
#endif
|
||||
|
||||
|
||||
/* Do we have full GC support? */
|
||||
|
||||
#if defined(MALLOC_smalloc) || defined(MALLOC_ptmalloc) || defined(MALLOC_slaballoc)
|
||||
# define GC_SUPPORT 1
|
||||
#endif
|
||||
|
||||
/* Do some of the selected packages require special treatment? */
|
||||
|
||||
/* SQLite in the threadsafe mode needs a normal malloc() */
|
||||
#if defined(SBRK_OK) && defined(USE_SQLITE)
|
||||
# undef SBRK_OK
|
||||
#endif
|
||||
|
||||
/* PTHREADS need a normal malloc() */
|
||||
#if defined(SBRK_OK) && (defined(USE_PTHREADS) || defined(SQLITE3_USES_PTHREADS))
|
||||
# undef SBRK_OK
|
||||
#endif
|
||||
|
||||
/* When we have allocation tracing, the allocator annotates every
|
||||
* allocation with the source filename and line where the allocation
|
||||
* occured. To allow the annotation of the allocations of higher structures
|
||||
* like strings with the place where the string as such is allocated (and not
|
||||
* the places in the string module), the following macros can be used
|
||||
* to declare and pass the necessary information transparently:
|
||||
*
|
||||
* MTRACE_DECL: the declaration of the tracing arguments
|
||||
* MTRACE_PASS: the tracing arguments when passed on to lower
|
||||
* functions
|
||||
* MTRACE_ARG: the tracing arguments on the toplevel call
|
||||
*/
|
||||
|
||||
#ifdef MALLOC_TRACE
|
||||
|
||||
#define MTRACE_DECL , const char * malloc_trace_file, int malloc_trace_line
|
||||
#define MTRACE_PASS , malloc_trace_file, malloc_trace_line
|
||||
#define MTRACE_ARG , __FILE__, __LINE__
|
||||
|
||||
#else
|
||||
|
||||
#define MTRACE_DECL
|
||||
#define MTRACE_PASS
|
||||
#define MTRACE_ARG
|
||||
|
||||
#endif
|
||||
|
||||
/* To function properly, MALLOC_(LPC_)TRACE need to be able to
|
||||
* test whether a memory block is free or not. This is reliably implemented
|
||||
* by MALLOC_CHECK.
|
||||
*/
|
||||
|
||||
#if (defined(MALLOC_TRACE) || defined(MALLOC_LPC_TRACE)) && !defined(MALLOC_CHECK)
|
||||
# define MALLOC_CHECK
|
||||
#endif
|
||||
|
||||
|
||||
/* This one is for backwards compatibility with old config.hs */
|
||||
|
||||
#if defined(NATIVE_MODE) && !defined(STRICT_EUIDS)
|
||||
# define STRICT_EUIDS
|
||||
#elif defined(COMPAT_MODE)
|
||||
# undef STRICT_EUIDS
|
||||
#endif
|
||||
|
||||
/* The string table is shadowed only in DEBUG mode */
|
||||
|
||||
#if !defined(DEBUG) && defined(CHECK_STRINGS)
|
||||
# undef CHECK_STRINGS
|
||||
#endif
|
||||
|
||||
/* The ALARM and HEART_BEAT time need to be at least 1. */
|
||||
|
||||
#if !defined(ALARM_TIME)
|
||||
#define ALARM_TIME 1
|
||||
#elif ALARM_TIME < 1
|
||||
#undef ALARM_TIME
|
||||
#define ALARM_TIME 1
|
||||
#endif
|
||||
|
||||
#if !defined(HEART_BEAT_INTERVAL)
|
||||
#define HEART_BEAT_INTERVAL 1
|
||||
#elif HEART_BEAT_INTERVAL < 1
|
||||
#undef HEART_BEAT_INTERVAL
|
||||
#define HEART_BEAT_INTERVAL 1
|
||||
#endif
|
||||
|
||||
/* Define some macros needed in the headers included from ../mudlib/sys */
|
||||
|
||||
#ifdef USE_IPV6
|
||||
# define __IPV6__
|
||||
#endif
|
||||
|
||||
/* Include the portability headers */
|
||||
#include "port.h"
|
||||
|
||||
/* TODO: this ctype-stuff might go into lex.h (impl in efun_defs.c) */
|
||||
#define _MCTe 0x01 /* escaped character in save/restore object. */
|
||||
#define _MCTd 0x02 /* numeric digit */
|
||||
#define _MCTt 0x04 /* delimiters in save/restore object. */
|
||||
|
||||
#define _MCTs 0x10 /* whitespace EXCLUDING '\n' */
|
||||
|
||||
#define _MCTx 0x40 /* hexadecimal */
|
||||
#define _MCTa 0x80 /* alphanumeric or '_' */
|
||||
extern unsigned char _my_ctype[];
|
||||
#define isescaped(c) (_my_ctype[(unsigned char)(c)]&_MCTe)
|
||||
#define issavedel(c) (_my_ctype[(unsigned char)(c)]&_MCTt)
|
||||
#define isalunum( c) (_my_ctype[(unsigned char)(c)]&_MCTa)
|
||||
#define lexdigit( c) (_my_ctype[(unsigned char)(c)]&_MCTd)
|
||||
|
||||
#ifndef MAXINT
|
||||
# define MAXINT (0x7fffffffU)
|
||||
#endif
|
||||
|
||||
/* A define to point out empty loop bodies. */
|
||||
#define NOOP
|
||||
|
||||
/* A macro to wrap statements */
|
||||
#define MACRO(x) do { x ; } while(0)
|
||||
|
||||
/* Determine the minimum of two values.
|
||||
* Some systems define this in system includes.
|
||||
*/
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#endif /* MIN */
|
||||
|
||||
#endif /* DRIVER_H__ */
|
432
src/dumpstat.c
Normal file
432
src/dumpstat.c
Normal file
|
@ -0,0 +1,432 @@
|
|||
/*---------------------------------------------------------------------------
|
||||
* Gamedriver - Dump object statistics.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
* Function to compute the memory usage of objects and dump their
|
||||
* statistics.
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "driver.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#include "dumpstat.h"
|
||||
#include "array.h"
|
||||
#include "closure.h"
|
||||
#include "exec.h"
|
||||
#include "filestat.h"
|
||||
#include "instrs.h" /* F_RETURN, F_RETURN0 for overhead computation */
|
||||
#include "mapping.h"
|
||||
#include "mstrings.h"
|
||||
#include "object.h"
|
||||
#include "ptrtable.h"
|
||||
#include "simulate.h"
|
||||
#include "stdstrings.h"
|
||||
#ifdef USE_STRUCTS
|
||||
#include "structs.h"
|
||||
#endif /* USE_STRUCTS */
|
||||
#include "svalue.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static size_t svalue_size(svalue_t *, mp_int *); /* forward */
|
||||
|
||||
/* Auxiliary structure for counting a mapping */
|
||||
|
||||
struct svalue_size_locals
|
||||
{
|
||||
mp_uint composite; /* Return: total composite memory usage of all elmts */
|
||||
mp_uint total; /* Return: total memory usage of all elmts */
|
||||
int num_values; /* Passed: width of the mapping */
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static struct pointer_table *ptable;
|
||||
/* The pointer_table to register all arrays and mappings.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void
|
||||
svalue_size_map_filter (svalue_t *key, svalue_t *values, void *extra)
|
||||
|
||||
/* Called for all keys in a mapping, it counts the size of the values
|
||||
* and returns the total in extra->num_values.
|
||||
*/
|
||||
|
||||
{
|
||||
struct svalue_size_locals *locals;
|
||||
mp_int total;
|
||||
int i;
|
||||
|
||||
locals = (struct svalue_size_locals*)extra;
|
||||
locals->composite += svalue_size(key, &total);
|
||||
locals->total += total;
|
||||
for(i = locals->num_values; --i >= 0; )
|
||||
{
|
||||
locals->composite += svalue_size(values++, &total) + sizeof(svalue_t);
|
||||
locals->total += total + sizeof(svalue_t);
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static size_t
|
||||
svalue_size (svalue_t *v, mp_int * pTotal)
|
||||
|
||||
/* Compute the memory usage of *<v> (modified to reflect data sharing),
|
||||
* calling svalue_size() recursively if necessary, and return it.
|
||||
* The size of *v itself is not included.
|
||||
* *<pUnshared> and *<pShared> are set to the total unshared and shared
|
||||
* datasize.
|
||||
*/
|
||||
|
||||
{
|
||||
mp_int i, composite, total, overhead;
|
||||
|
||||
assert_stack_gap();
|
||||
|
||||
*pTotal = 0;
|
||||
|
||||
total = overhead = composite = 0;
|
||||
|
||||
switch(v->type)
|
||||
{
|
||||
case T_OBJECT:
|
||||
case T_NUMBER:
|
||||
case T_FLOAT:
|
||||
return 0;
|
||||
|
||||
case T_STRING:
|
||||
case T_SYMBOL:
|
||||
*pTotal = mstr_mem_size(v->u.str);
|
||||
return *pTotal / v->u.str->info.ref;
|
||||
|
||||
case T_MAPPING:
|
||||
{
|
||||
struct svalue_size_locals locals;
|
||||
|
||||
if (NULL == register_pointer(ptable, v->u.map) ) return 0;
|
||||
|
||||
overhead = (mp_uint)mapping_overhead(v->u.map);
|
||||
locals.total = 0;
|
||||
locals.composite = 0;
|
||||
locals.num_values = v->u.map->num_values;
|
||||
walk_mapping(v->u.map, svalue_size_map_filter, &locals);
|
||||
|
||||
*pTotal = locals.total + overhead;
|
||||
return (overhead + locals.composite) / v->u.map->ref;
|
||||
}
|
||||
|
||||
case T_POINTER:
|
||||
case T_QUOTED_ARRAY:
|
||||
{
|
||||
if (v->u.vec == &null_vector) return 0;
|
||||
if (NULL == register_pointer(ptable, v->u.vec) ) return 0;
|
||||
overhead = sizeof *v->u.vec - sizeof v->u.vec->item +
|
||||
sizeof(svalue_t) * v->u.vec->size + sizeof(char *);
|
||||
for (i=0; i < (mp_int)VEC_SIZE(v->u.vec); i++) {
|
||||
composite += svalue_size(&v->u.vec->item[i], &total);
|
||||
*pTotal += total;
|
||||
}
|
||||
*pTotal += overhead;
|
||||
return (overhead + composite) / v->u.vec->ref;
|
||||
}
|
||||
|
||||
#ifdef USE_STRUCTS
|
||||
case T_STRUCT:
|
||||
{
|
||||
struct_t *st = v->u.strct;
|
||||
if (NULL == register_pointer(ptable, st) ) return 0;
|
||||
overhead = sizeof *st - sizeof st->member
|
||||
+ sizeof(svalue_t) * struct_size(st);
|
||||
for (i=0; i < (mp_int)struct_size(st); i++) {
|
||||
composite += svalue_size(&st->member[i], &total);
|
||||
*pTotal += total;
|
||||
}
|
||||
*pTotal += overhead;
|
||||
return (overhead + composite) / st->ref;
|
||||
}
|
||||
#endif /* USE_STRUCTS */
|
||||
|
||||
case T_CLOSURE:
|
||||
{
|
||||
int num_values;
|
||||
svalue_t *svp;
|
||||
lambda_t *l;
|
||||
|
||||
if (!CLOSURE_MALLOCED(v->x.closure_type)) return 0;
|
||||
if (!CLOSURE_REFERENCES_CODE(v->x.closure_type))
|
||||
{
|
||||
#ifdef USE_NEW_INLINES
|
||||
if (v->x.closure_type == CLOSURE_LFUN)
|
||||
composite = SIZEOF_LAMBDA(v->u.lambda->function.lfun.context_size);
|
||||
else /* CLOSURE_IDENTIFIER || CLOSURE_PRELIMINARY */
|
||||
composite = sizeof *v->u.lambda;
|
||||
|
||||
composite += sizeof(char *);
|
||||
#else
|
||||
/* CLOSURE_LFUN || CLOSURE_IDENTIFIER || CLOSURE_PRELIMINARY */
|
||||
composite = sizeof *v->u.lambda + sizeof(char *);
|
||||
#endif
|
||||
*pTotal = composite;
|
||||
return composite / v->u.lambda->ref;
|
||||
}
|
||||
/* CLOSURE_LAMBDA */
|
||||
composite = overhead = 0;
|
||||
l = v->u.lambda;
|
||||
if (v->x.closure_type == CLOSURE_BOUND_LAMBDA)
|
||||
{
|
||||
total = sizeof *l - sizeof l->function + sizeof l->function.lambda;
|
||||
*pTotal += total;
|
||||
composite += total / l->ref;
|
||||
l = l->function.lambda;
|
||||
}
|
||||
num_values = EXTRACT_UCHAR(&l->function.code[0]);
|
||||
if (num_values == 0xff)
|
||||
num_values = ((svalue_t *)l)[-0xff].u.number;
|
||||
svp = (svalue_t *)l - num_values;
|
||||
if (NULL == register_pointer(ptable, svp)) return 0;
|
||||
overhead = sizeof(svalue_t) * num_values + sizeof (char *);
|
||||
{
|
||||
bytecode_p p = &l->function.code[2];
|
||||
do {
|
||||
++p;
|
||||
switch(GET_CODE(p)) {
|
||||
case F_RETURN:
|
||||
case F_RETURN0:
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} while (1);
|
||||
overhead += (p - (bytecode_p)l + (sizeof(bytecode_p) - 1))
|
||||
& ~(sizeof(bytecode_p) - 1);
|
||||
}
|
||||
|
||||
while (--num_values >= 0)
|
||||
{
|
||||
composite += svalue_size(svp++, &total);
|
||||
*pTotal += total;
|
||||
}
|
||||
|
||||
*pTotal += overhead;
|
||||
return (overhead + composite) / l->ref;
|
||||
}
|
||||
|
||||
default:
|
||||
fatal("Illegal type: %d\n", v->type);
|
||||
}
|
||||
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
mp_int
|
||||
data_size (object_t *ob, mp_int * pTotal)
|
||||
|
||||
/* Compute the memory usage (modified to reflect shared data use)
|
||||
* of the data held by object <ob> and return it.
|
||||
* If the object is swapped out or has no variables, return 0.
|
||||
*
|
||||
* If <pTotal> is given, *<pTotal> is set to the raw datasize.
|
||||
*/
|
||||
|
||||
{
|
||||
mp_int total = sizeof(p_int); /* smalloc overhead */
|
||||
int i;
|
||||
svalue_t *svp;
|
||||
|
||||
if (pTotal != NULL)
|
||||
*pTotal = 0;
|
||||
|
||||
if (ob->flags & O_SWAPPED || !(i = ob->prog->num_variables) )
|
||||
return 0;
|
||||
ptable = new_pointer_table();
|
||||
if (!ptable)
|
||||
errorf("(dumpstat) Out of memory for new pointer table.\n");
|
||||
for (svp = ob->variables; --i >= 0; svp++)
|
||||
{
|
||||
mp_int tmp;
|
||||
total += svalue_size(svp, &tmp) + sizeof (svalue_t);
|
||||
if (pTotal != NULL)
|
||||
*pTotal += tmp + sizeof(svalue_t);
|
||||
}
|
||||
free_pointer_table(ptable);
|
||||
return total;
|
||||
} /* data_size() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
mp_int
|
||||
program_string_size (program_t *prog, mp_int * pOverhead, mp_int * pData)
|
||||
|
||||
/* Compute the composite data size of all strings in program <prog>
|
||||
* which must be swapped in.
|
||||
* Set *<pOverhead> to the size of the overhead in the program structure,
|
||||
* and *<pData> to the raw data size of the strings.
|
||||
*/
|
||||
|
||||
{
|
||||
int i;
|
||||
mp_int rc, data;
|
||||
|
||||
rc = data = 0;
|
||||
|
||||
for (i = prog->num_strings; i--; )
|
||||
{
|
||||
string_t * str = prog->strings[i];
|
||||
mp_int size;
|
||||
|
||||
size = mstr_mem_size(str);
|
||||
data += size;
|
||||
rc += size / str->info.ref;
|
||||
}
|
||||
|
||||
*pOverhead = prog->num_strings * sizeof(char *);
|
||||
*pData = data;
|
||||
return rc;
|
||||
} /* program_string_size() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
Bool
|
||||
dumpstat (string_t *fname)
|
||||
|
||||
/* This function dumps statistics about all listed objects into the file
|
||||
* $MUDLIB/<fname>. It is called by the command parser or from debug_info.
|
||||
* Return TRUE on success, FALSE if <fname> can't be written.
|
||||
*/
|
||||
|
||||
{
|
||||
FILE *f;
|
||||
object_t *ob;
|
||||
|
||||
static char *swapstrings[] =
|
||||
{"", "PROG SWAPPED", "VAR SWAPPED", "SWAPPED", };
|
||||
|
||||
fname = check_valid_path(fname, current_object, STR_OBJDUMP, MY_TRUE);
|
||||
if (!fname)
|
||||
return MY_FALSE;
|
||||
f = fopen(get_txt(fname), "w");
|
||||
if (!f)
|
||||
{
|
||||
free_mstring(fname);
|
||||
return MY_FALSE;
|
||||
}
|
||||
FCOUNT_WRITE(get_txt(fname));
|
||||
|
||||
for (ob = obj_list; ob; ob = ob->next_all)
|
||||
{
|
||||
mp_int compsize, totalsize, overhead;
|
||||
char timest[21];
|
||||
struct tm *tm;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (ob->flags & O_DESTRUCTED) /* TODO: Can't happen */
|
||||
continue;
|
||||
#endif
|
||||
compsize = data_size(ob, &totalsize);
|
||||
|
||||
if (!O_PROG_SWAPPED(ob)
|
||||
&& (ob->prog->ref == 1 || !(ob->flags & (O_CLONE|O_REPLACED))))
|
||||
{
|
||||
overhead = ob->prog->total_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
overhead = 0;
|
||||
}
|
||||
|
||||
overhead += sizeof (object_t);
|
||||
|
||||
fprintf(f, "%-20s %5ld (%5ld) ref %2ld %s "
|
||||
, get_txt(ob->name)
|
||||
, compsize + overhead, totalsize + overhead
|
||||
, ob->ref
|
||||
, ob->flags & O_HEART_BEAT ? "HB" : " "
|
||||
);
|
||||
#ifdef USE_INVENTORIES
|
||||
if (ob->super)
|
||||
fprintf(f, "%s ", get_txt(ob->super->name));
|
||||
else
|
||||
#endif
|
||||
fprintf(f, "-- ");
|
||||
|
||||
if (ob->gigaticks)
|
||||
fprintf(f, " (%lu%09lu)", ob->gigaticks, ob->ticks);
|
||||
else
|
||||
fprintf(f, " (%lu)", ob->ticks);
|
||||
fprintf(f, " %s",
|
||||
swapstrings[(O_PROG_SWAPPED(ob)?1:0) | (O_VAR_SWAPPED(ob)?2:0)]
|
||||
);
|
||||
tm = localtime((time_t *)&ob->load_time);
|
||||
strftime(timest, sizeof(timest)-1, "%Y.%m.%d-%H:%M:%S", tm);
|
||||
fprintf(f, " %s\n", timest);
|
||||
}
|
||||
fclose(f);
|
||||
free_mstring(fname);
|
||||
|
||||
return MY_TRUE;
|
||||
} /* dumpstat() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
Bool
|
||||
dumpstat_dest(string_t *fname)
|
||||
|
||||
/* this function dumps statistics about all destructed objects into the file
|
||||
* $MUDLIB/<fname>. It is called by the commandparser and by debug_info().
|
||||
* Return TRUE on success, FALSE if <fname> can't be written.
|
||||
*/
|
||||
|
||||
{
|
||||
FILE *f;
|
||||
object_t *ob;
|
||||
|
||||
fname = check_valid_path(fname, current_object, STR_OBJDUMP, MY_TRUE);
|
||||
if (!fname)
|
||||
return MY_FALSE;
|
||||
f = fopen(get_txt(fname), "w");
|
||||
if (!f)
|
||||
{
|
||||
free_mstring(fname);
|
||||
return MY_FALSE;
|
||||
}
|
||||
FCOUNT_WRITE(get_txt(fname));
|
||||
|
||||
for (ob = newly_destructed_objs; ob; ob = ob->next_all)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!(ob->flags & O_DESTRUCTED)) /* TODO: Can't happen */
|
||||
continue;
|
||||
#endif
|
||||
fprintf(f, "%-20s ref %2ld NEW\n"
|
||||
, get_txt(ob->name)
|
||||
, ob->ref
|
||||
);
|
||||
}
|
||||
|
||||
for (ob = destructed_objs; ob; ob = ob->next_all)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!(ob->flags & O_DESTRUCTED)) /* TODO: Can't happen */
|
||||
continue;
|
||||
#endif
|
||||
fprintf(f, "%-20s ref %2ld\n"
|
||||
, get_txt(ob->name)
|
||||
, ob->ref
|
||||
);
|
||||
}
|
||||
fclose(f);
|
||||
free_mstring(fname);
|
||||
return MY_TRUE;
|
||||
} /* dumpstat_dest() */
|
||||
|
||||
/***************************************************************************/
|
||||
|
12
src/dumpstat.h
Normal file
12
src/dumpstat.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef DUMPSTAT_H__
|
||||
#define DUMPSTAT_H__ 1
|
||||
|
||||
#include "driver.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
extern mp_int data_size (object_t *ob, mp_int * pTotal);
|
||||
extern mp_int program_string_size (program_t *prog, mp_int * pOverhead, mp_int * pData);
|
||||
extern Bool dumpstat(string_t *name);
|
||||
extern Bool dumpstat_dest(string_t *name);
|
||||
|
||||
#endif /* DUMPSTAT_H__ */
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue