<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>泥巴客栈</title><link>http://www.xiaqiang.com.cn/</link><description>人心动一念 天地尽相知 善恶若无报 乾坤必有私</description><generator>RainbowSoft Studio Z-Blog 2.3 Avengers Build 180518</generator><language>zh-CN</language><pubDate>Tue, 18 Jun 2024 14:13:57 +0800</pubDate><item><title>mips交叉编译fluffos过程总结【原作者mok】</title><author>null@null.com (xiaqiang)</author><link>http://www.xiaqiang.com.cn/post/21.html</link><pubDate>Wed, 11 Mar 2020 10:51:29 +0800</pubDate><guid>http://www.xiaqiang.com.cn/post/21.html</guid><description><![CDATA[<p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">1.先装好交叉编译的环境，例如mips，安装好mipsel-linux-gnu-g++的工具链</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">sudo apt-get install gcc-mipsel-linux-gnu</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">sudo apt-get install g++-mipsel-linux-gnu</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">下载必要库的源码--没错是源码</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">libevent prce libz openssl</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">./configure --host=mipsel-linux-gnu&nbsp;</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">make</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">make install</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">这样环境就完成了。</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">sudo dpkg-reconfigure dash 选no 关闭dash这步非常重要。</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">会导致bash运行出错。</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);"><br style="padding: 0px; margin: 0px;"/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">2.先用原来环境编译一次</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">./builf.FluffOS</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">make</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">获得并备份以下5个文件：</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">vm/internal/compiler/grammar.autogen.y</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">vm/internal/applies_table.autogen.cc</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">vm/internal/applies_table.autogen.h</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">vm/internal/efuns.autogen.cc</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">vm/internal/efuns.autogen.h</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">make clean命令清除</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">把以上的5个备份文件复杂回原来的目录里面。</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);"><br style="padding: 0px; margin: 0px;"/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">3.修改configure.h</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">删除</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">#define malloc rpl_malloc</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">#define realloc rpl_realloc</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">两行</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);"><br style="padding: 0px; margin: 0px;"/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">4.修改makefile文件</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">CXX=g++ 改为CAA=g++</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">增加一项,内容为CXX=mipsel-linux-gnu-g++ 你需要的编译器</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);"><br style="padding: 0px; margin: 0px;"/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">复制CXXFLAGS=的所有内容</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">增加一项，CAAFLAGS=内容为以上复杂的内容，修改其中-march=的内容，该为你需要的cpu型号，例如-march=mips32r2</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);"><br style="padding: 0px; margin: 0px;"/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">把USE_JEMALLOC=1 改为USE_JEMALLOC=0</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">把@echo &#39;#define USE_JEMALLOC 1&#39; &gt;&gt; cc.h 改为@echo &#39;#define USE_JEMALLOC 0&#39; &gt;&gt; cc.h</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);"><br style="padding: 0px; margin: 0px;"/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">找到并删除以下3句</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">@./tools/build_applies.autogen</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">@./tools/make_func.autogen packages/packages.autogen.fullspec</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">@./tools/make_grammar.sh $(CXX) $(CXXFLAGS)</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);"><br style="padding: 0px; margin: 0px;"/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">找到</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">$(CXX) $(CXXFLAGS) -x c++ dtrace_compile.cc -o dtrace_compile</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">修改为</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">$(CAA) $(CAAFLAGS) -x c++ dtrace_compile.cc -o dtrace_compile</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);"><br style="padding: 0px; margin: 0px;"/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">5.修改dtrace_compile.cc</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">找到64，修改为32</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);"><br style="padding: 0px; margin: 0px;"/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">6.make 恭喜你完成了交叉编译</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);"><br style="padding: 0px; margin: 0px;"/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;--by mok&nbsp;</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2017.8.11</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);"><br style="padding: 0px; margin: 0px;"/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);"><br style="padding: 0px; margin: 0px;"/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">使用前授权 chmod -v +x ./driver</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">另外自行安装必要的裤头</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">libpcre.so.1</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">libc.so.6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; libstdc++.so.6</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">libc6_2.19-18+deb8u10_mipsel.deb &nbsp;libstdc++6_7.1.0-13_mipsel.deb</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">libevent-2.1.so.6</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);"><br style="padding: 0px; margin: 0px;"/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">9月7日版本交叉编译问题</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">#<span class="Apple-tab-span" style="padding: 0px; margin: 0px; white-space: pre;">	</span>@ASAN_OPTIONS=&quot;detect_leaks=0&quot; ./tools/make_func.autogen packages/packages.autogen.fullspec</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">把这句注释掉就ok</p><p style="padding: 0px; margin-top: 0px; margin-bottom: 10px; color: rgb(34, 34, 34); font-family: 微软雅黑, 宋体, &quot;Trebuchet MS&quot;, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2017.9.18</p><p><br/></p>]]></description><category>Mud</category><comments>http://www.xiaqiang.com.cn/post/21.html#comment</comments><wfw:commentRss>http://www.xiaqiang.com.cn/feed.asp?cmt=21</wfw:commentRss></item><item><title>call_out()函数小结</title><author>null@null.com (xiaqiang)</author><link>http://www.xiaqiang.com.cn/post/20.html</link><pubDate>Wed, 11 Mar 2020 10:47:48 +0800</pubDate><guid>http://www.xiaqiang.com.cn/post/20.html</guid><description><![CDATA[<p>转：（我也不知道哪年从internat上 copy save下来的）</p><p>因为reallove的帖子，我算是第一次较为仔细的看了一遍call_out()在driver中的机理，也明确了不少以前似是而非的概念。现整理如下：</p><p><br/></p><p>1. 关于call_out()的driver级宏开关有两个（均在options.h当中）：</p><p><br/></p><p>&nbsp; &nbsp; a. THIS_PLAYER_IN_CALL_OUT</p><p><br/></p><p>&nbsp; &nbsp; 该宏被define时，我们可以在被延时呼叫的函数中肆无忌惮的使用this_player()来找到call_out定义时的this_player()，反之则无法找到准确的this_player()（也就是说，可能找到一个谁，但这个“谁”应该与定义call_out时的“谁”毫无瓜葛，肯定不是我们希望的那一个就对了）</p><p><br/></p><p>&nbsp; &nbsp; b. CALLOUT_HANDLES</p><p><br/></p><p>&nbsp; &nbsp; 该宏被定义时，call_out()原型变成了 int call_out(function foo,int delay, ..)，返回值是该call_out的唯一句柄，我们可以在remove_call_out()时以此为参数清理掉“这一个”而非“这一类”call_outs</p><p><br/></p><p>&nbsp;</p><p><br/></p><p>2. 关于call_out的作用时机和delay的详细含义：</p><p><br/></p><p>&nbsp; &nbsp; 已知call_out记录是以链表与delay的某个余数分类的形式进行存储的。</p><p><br/></p><p>&nbsp; &nbsp; call_out会在每个系统心跳（不是每个人的心跳，而是说，系统每次呼叫完所有心跳）之后进入对call_out们的处理（仔细的说，driver中call_out.c中的call_out()函数就是干这个事情的）。</p><p><br/></p><p>&nbsp; &nbsp; 因此，就我现在阅读driver代码得到的结论，可以确定的说，call_out一定在心跳点上发作，但会有累积发作的模式。</p><p><br/></p><p>&nbsp; &nbsp;&nbsp;</p><p><br/></p><p>&nbsp; &nbsp;在解释delay之前，有几个“时间”需要说明：</p><p><br/></p><p>&nbsp; &nbsp;a. heart_beat()的发作时间：driver通过一个alarm/singal事件来设置hb的标志位，并在backend()的大循环当中不停检查该标志位的状态以决定是否应该触发hb，因此通常可以认为hb的发作较为准确。虽然从代码中看，在不同系统下的编译中，driver使用了alarm和ualarm两种不同方式进行按秒或按微秒级别的触发事件，但不那么精确的描述下，还是可以认为心跳的准时程度较高，更接近与真实系统时间。</p><p><br/></p><p>&nbsp; &nbsp;b. call_out被插入和判断是否被执行（注意不是是否进入call_out执行过程，而是进入后的“判断”），依据的是另外一个时间标记current_time。该标记在系统启动的时候被设置为当前时间的秒数（unix_time，也就是我们常看到的1239xxxxxxxx这种），其后只在系统心跳时被重置为“当前”。因此这个时间标并不总是等于真实的时间。特别是在hb大于1秒的情况下，如果以真实的秒为ticker来审视它，可能会是：0,0,0,[1,2,3],3,3,3,[4,5,6]这样的情况，即很多秒不变化，然后在同一个时间点上依次++直到追上真实时间。</p><p><br/></p><p>&nbsp;</p><p><br/></p><p>&nbsp; &nbsp; 于是，关于delay有如下看法：</p><p><br/></p><p>&nbsp; &nbsp; a.在插入一条新的call_out时，delay看起来是从“现在”加上delay秒数后执行被呼叫函数，但这个“现在”是current_time指定的现在，hb&gt;1sec时，他通常指的是过去。。。，因此当我们call_out(foo,3)的时候，他不一定指的是现在+3秒，而是指time()+3秒，他也不一定真的在三秒后执行。不考虑毫秒位的话，通常只有hb为1秒的时候，上面的描述才较为精确。但另外一个方面，delay的含义更倾向于秒，而不是hb。。。（我觉得我已经无法用人类的语言解释清楚这个破玩意儿了。。。。）</p><p><br/></p><p>&nbsp; &nbsp; b.如前述，call_out被执行一定是在hb的执行点上，具体的执行方式是：在某个HB执行点上，系统扫描小于current_time的call_out记录，然后依次执行（链表的原因，对于应该在“同一个时间点被执行的callout”，先入先执行）。然后系统对current_time++，继续上一步操作，知道current_time追赶上“现在”。</p><p><br/></p><p>&nbsp;</p><p><br/></p><p>&nbsp; &nbsp; 所以说，如果你期望call_out表现比较正常，那最好把hb设为1秒（1000000微秒）；否则hb越大，callout的表现就越奇怪。hb非整秒数则会带来其他更微妙的改变。。。。</p><p><br/></p><p>&nbsp;</p><p><br/></p><p>&nbsp;</p><p><br/></p><p>&nbsp; &nbsp; 最后，关于call_out(foo,0)这个特例。</p><p><br/></p><p>&nbsp; &nbsp; 一般来说，我们无法期待这个东西立刻执行。他可能会在下一次hb的时候才被执行。</p><p><br/></p><p>&nbsp; &nbsp; 之所以用“可能”，是因为这个特例还有个更奇怪的特例。该call_out本身处于另外一个call_out的呼叫函数当中。因此这个call_out进行的记录插入动作本身就是在call_out执行点上。可想而知，他立刻就被执行了！！！</p><p><br/></p><p>&nbsp;</p><p><br/></p><p>&nbsp; &nbsp; 我们举两个例子来说明吧：</p><p><br/></p><p>&nbsp; &nbsp; 我们假设hb是10个seconds。查看这样一段函数：</p><p><br/></p><p>void test()</p><p><br/></p><p>{</p><p><br/></p><p>&nbsp; &nbsp; &nbsp; &nbsp; call_out(&quot;test_callout&quot;,0);</p><p><br/></p><p>}</p><p><br/></p><p>&nbsp;</p><p><br/></p><p>void test_callout()</p><p><br/></p><p>{</p><p><br/></p><p>&nbsp; &nbsp; &nbsp; &nbsp; tell_object(this_object(),sprintf(&quot;CO:%d\n&quot;,time()));</p><p><br/></p><p>&nbsp; &nbsp; &nbsp; &nbsp; call_out(&quot;test_callout&quot;,0);</p><p><br/></p><p>}</p><p><br/></p><p>&nbsp;</p><p><br/></p><p>当我们以某种形式执行了test()的时候，会出现什么状况呢？</p><p><br/></p><p>首先是test()中的：call_out(&quot;test_callout&quot;,0)被执行，插入了一条记录，这个记录应当被触发的时间点是current_time+0。（我们假设current_time是333秒吧）</p><p><br/></p><p>但考虑到hb点还没到。这个时候我们什么都看不到。</p><p><br/></p><p>等到下一个hb点，也许作为现实时间，是337秒的时候吧（举例）。</p><p><br/></p><p>上次插入的callout被执行了！</p><p><br/></p><p>因此我们收到一条CO:333的显示信息（因为current_time这个时候还没++完呢）</p><p><br/></p><p>接下来就坏掉了，因为又一个call_out(&quot;test_callout&quot;,0)被执行了！</p><p><br/></p><p>要注意，这一条call_out插入的触发时间点依然是current_time+0，也就是333。</p><p><br/></p><p>这时这个test_callout函数被执行完，退出，回到系统的call_out执行循环当中。</p><p><br/></p><p>坏掉了，系统发现在333这个时间点上还有个未处理的记录（刚插进去的。。）</p><p><br/></p><p>于是进入了死循环。。。</p><p><br/></p><p>我们会看到系统不断刷屏CO:333</p><p><br/></p><p>CO:333</p><p><br/></p><p>CO:333</p><p><br/></p><p>CO:333</p><p><br/></p><p>。。。。</p><p><br/></p><p>死循环下去了。</p><p><br/></p><p>&nbsp;</p><p><br/></p><p>上面这个例子表明，callout 0是否立刻被执行，要看他所处的环境，不能一概而论，即时hb是1也如此。</p><p><br/></p><p>&nbsp;</p><p><br/></p><p>再来一个例子：</p><p><br/></p><p>同样hb是10seconds。</p><p><br/></p><p>&nbsp;</p><p><br/></p><p>void test()</p><p><br/></p><p>{</p><p><br/></p><p>&nbsp; &nbsp; &nbsp; &nbsp; call_out(&quot;test_callout&quot;,0);</p><p><br/></p><p>}</p><p><br/></p><p>&nbsp;</p><p><br/></p><p>void test_callout(){</p><p><br/></p><p>&nbsp; &nbsp; &nbsp; &nbsp; tell_object(this_object(),sprintf(&quot;CO:%d\n&quot;,time()));&nbsp; &nbsp; &nbsp; &nbsp; call_out(&quot;test_callout&quot;,1);</p><p><br/></p><p>}差别是后一个call_out的delay是1。</p><p><br/></p><p>&nbsp;</p><p><br/></p><p>不详细描述了，我们得到的结果应该是类似：</p><p><br/></p><p>系统等待发呆。。。。一次性刷屏：</p><p><br/></p><p>CO:333</p><p><br/></p><p>CO:334</p><p><br/></p><p>CO:335</p><p><br/></p><p>CO:336</p><p><br/></p><p>CO:337</p><p><br/></p><p>继续等待发呆个10秒。。。一次性刷屏：</p><p><br/></p><p>CO:338</p><p><br/></p><p>CO:339</p><p><br/></p><p>CO:340</p><p><br/></p><p>CO:341</p><p><br/></p><p>CO:342</p><p><br/></p><p>CO:343</p><p><br/></p><p>CO:344</p><p><br/></p><p>CO:345</p><p><br/></p><p>CO:346</p><p><br/></p><p>CO:347</p><p><br/></p><p>等待。。。刷屏。。。等待。。。刷屏。。。。</p><p>————————————————</p><p>版权声明：本文为CSDN博主「回到未来望过去」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。</p><p>原文链接：https://blog.csdn.net/viviliving/article/details/100553285</p><p><br/></p>]]></description><category>Mud</category><comments>http://www.xiaqiang.com.cn/post/20.html#comment</comments><wfw:commentRss>http://www.xiaqiang.com.cn/feed.asp?cmt=20</wfw:commentRss></item><item><title>系统刷新与内存清除分析</title><author>null@null.com (xiaqiang)</author><link>http://www.xiaqiang.com.cn/post/19.html</link><pubDate>Mon, 20 Feb 2017 17:23:01 +0800</pubDate><guid>http://www.xiaqiang.com.cn/post/19.html</guid><description><![CDATA[<p style="text-align:left;">原作者：未知</p><p style="text-align:left;">&nbsp; &nbsp; &nbsp; &nbsp;有关系统更新一直是玩家乃至于新巫师们关心的问题。比如，为何每隔15分钟大多数房间里杀死的NPC会重生？跑到别处或被玩家背到别处的NPC怎么会跑回去？为什么有的NPC跑不回去？什么有的东西会重生？为什么又有的东西只要别的玩家放在身上？等等。<br/>　　目前主流MUDLIB都是ES系列的。从ES系列沿袭下来的更新都是通过ROOM的更新实现的。而ROOM的更新则是由MUDOS里的设置每隔一定时间（一般是15分钟）调用一次所有的有reset()函数的房间。而这个reset()函数则写在ROOM的标准继承文件里面。下面我们则来看看ROOM是如何实现房间里的生物、物品的重生或更新：<br/>　　在写这篇文章之前，正好在网上看到darks兄写的《ROOM的结构》，于是我这篇文章的不少地方也就写得很顺畅了，有些直接引用了《ROOM》一文的一些内容。为了尊重原作者，凡是引用或出自darks兄的原文内容我都用“”与绿色标出：<br/>　　ROOM的标准文件由于MUDLIB的不同，放在目录路径也不同，但大多情况下也就是/inherit/room/下或者与/obj/room/下两种可能而已。反正不检查一下在/include/下的globals.h，看这个文件里ROOM是定义在哪里就可以了，下面来看一看room.c的程序详解：</p><p style="text-align:left;">inherit F_DBASE;<br/><span style="color:#006666">//“<span style="color:#006600">这个是继承dbase标准继承，有了它，你才可使用set等函数为这个物件设定变数</span>”（此问题日后做专题说明）。</span></p><p style="text-align:left;">inherit F_CLEAN_UP;<br/><span style="color:#006666">//“<span style="color:#336600">这个用来定时清除很久没被访问的room</span>”，这个概念我们要在后面谈到。</span></p><p style="text-align:left;">static mapping doors;<br/><span style="color:#006666">//“<span style="color:#336600">这是一个有关房间里的门的全局变量，不是我们今天讨论的范围之内，你只要知道就行，我们在这个文件里还能找到与门相关的几个函数：</span>”</span></p><p style="text-align:left;">mixed set_door(string dir, string prop, mixed data)<br/>mixed 
query_door(string dir, string prop)<br/>mapping query_doors()<br/>string 
look_door(string dir)<br/>varargs int open_door(string dir, int 
from_other_side)<br/>varargs int close_door(string dir, int 
from_other_side)<br/>varargs int lock_door(string dir, string key, int 
from_other_side)<br/>varargs int unlock_door(string dir, string key, int 
from_other_side)<br/>int check_door(string dir, mapping door)<br/>varargs void 
create_door(string dir, mixed data, string other_side_dir, int status)<br/>int 
valid_leave(object me, string dir)<br/>int query_max_encumbrance() { return 
100000000000; } <span style="color:#006666"><br/>//设置可容纳的重量，以上这些函数大多与门有关，我们今天都一一略过，下面才是我们今天要研究的与系统房间刷新相关的函数：</span></p><p style="text-align:left;">object make_inventory(string file)<br/>{<br/>　　object ob;<br/>　　ob = 
new(file);<br/><span style="color:#006666">//根据传递来的路径名，将ob复制出来</span> <br/>　　ob-&gt;move(this_object());<br/><span style="color:#006666">//复制出来的ob移于目的地</span> <br/>　　ob-&gt;set(&quot;startroom&quot;, base_name(this_object()));<br/>　　return 
ob;<br/>}<br/><span style="color:#006666">//这个函数用来产生一个房间里的物品。首先它需要别的函数在调用它的时候要传递给它一个需要产生的物件的路径。然后用new()复制出来，接着move到这个房间里，再接着给它设上startroom这个标记，这个标记就可以在这个房间定时呼叫自己房间里产生的npc可以使用return_home()这个函数时，正确回到原来的地方。</span></p><p style="text-align:left;">void reset()<br/>{<br/>　　mapping ob_list, ob;<br/>　　string 
*list;<br/>　　int i,j;</p><p style="text-align:left;">　　set(&quot;no_clean_up&quot;, 0);<br/><span style="color:#006666">//“<span style="color:#336600">这个标记为零，即允许系统到了规定时间将这个文件扫出内存，那么这个文件内的所有东西都会消失。由于room标准继承有这句，似乎发现只要继承它的房间文件无论写为0/1都是无效的，因为都会在这里被清除成零。</span>”</span></p><p style="text-align:left;">　　ob_list = query(&quot;objects&quot;);<br/><span style="color:#006666">//先取出一个这个房间初始设定的objects的映射集</span><br/>　　if( !mapp(ob_list) ) 
return;<br/><span style="color:#006666">//如果这个房间初始时就没有设定有生物物品，就说明根本无需要刷新，因此到此返回。</span></p><p style="text-align:left;">　　if( !mapp(ob = query_temp(&quot;objects&quot;)) )<br/>　　ob = 
allocate_mapping(sizeof(ob_list));<br/><span style="color:#006666">//程序到后面才可看到ob = 
query_temp(&quot;objects&quot;)是如何出来的，在这里，我们先不管，你只要知道，如果是一个刚刚编译进内存的房间，是不会有ob这个映射集的，因此需要用allocate_mapping按照ob_list的多少为这个新设定的映射集ob分配内存大小。</span></p><p style="text-align:left;">　　list = keys(ob_list);<br/><span style="color:#006666">//从ob_list映射中取出关键字组成一个新数组。</span></p><p style="text-align:left;">　　for(i=0; i&lt;sizeof(list); i++)<br/><span style="color:#006666">//开始循环检查这个数组里的每一项</span> <br/>　　{<br/>　　　　if( 
undefinedp(ob[list[i]])<br/>　　　　　　&amp;&amp; 
intp(ob_list[list[i]])<br/>　　　　　　&amp;&amp; ob_list[list[i]] &gt; 1 
)<br/>　　　　　　ob[list[i]] = allocate(ob_list[list[i]]);<br/><span style="color:#006666">//如果房间里曾经定义了要产生物品，并且数量不止一个的话，就要进行ob[list[i]]这个物件数组的内存分配</span></p><p style="text-align:left;">　　　　switch(ob_list[list[i]])<br/>　　　　{<br/>　　　　case 1:<br/><span style="color:#006666">//举例一个文件里：set(&quot;objects&quot;,([&quot;/d/city/npc/bing&quot;:1]));，那么在这里，也就是ob_list[list[i]]这个值取出是1</span></p><p style="text-align:left;">　　　　　　if( !ob[list[i]] )<br/>　　　　　　　　ob[list[i]] = 
make_inventory(list[i]);<br/><span style="color:#006666">//如果这一个对象已经不在了（玩家理解的就是被杀死了或被当作任务送掉了，巫师的理解就是被destruct了），就使用make_inventory()函数再重新制造一个放进来。这里注意了，仁去递过去的list[i]就是这一项物品的路径名，正因为有了路径名，make_inventory()函数才能正确制造出新的来。</span></p><p style="text-align:left;">　　　　　　if( environment(ob[list[i]]) != this_object())<br/><span style="color:#006666">//反之如果还存在，但它目前所处之地却不是目前的这个房间</span></p><p style="text-align:left;">　　　　　　{<br/>　　　　　　　　if(ob[list[i]]-&gt;is_character()<br/>　　　　　　　　　　&amp;&amp;!ob[list[i]]-&gt;return_home(this_object()))<br/>　　　　　　　　add(&quot;no_clean_up&quot;,1);<br/><span style="color:#006666">//这句判断该物体如果是生物，就呼叫生物的return_home()叫它回来，如果这个NPC不能回来并且返回值是0的话，就会给这个房间增加一次no_clean_up的记号，程序的原作者之所以要在这里增加房间的no_clean_up记号，估计它的意思就是不想让系统在房间不能成功召回自己的NPC的情况下清除它，因为它想在以后的刷新中再把它呼叫回来。但是实际上，大家注意到前面的程序了吧，只要产生了下一次呼叫reset()时，前面就会把no_clean_up设为0，因此这段ES的源程有些莫名其妙，但大家居然都没人改，也是怪事。<br/></span><br/>　　　　　　}<br/>　　　　　　break;<br/>　　　　　　default:<br/><span style="color:#006666">//除此之外，也就是物件不止一个的话，举例相当于文件里：set(&quot;objects&quot;,([&quot;/d/city/npc/bing&quot;:2]))或者3,4....这类的情况</span></p><p style="text-align:left;">　　　　　　for(j=0; j&lt;ob_list[list[i]]; 
j++)<br/>　　　　　　{<br/>　　　　　　　　if( !objectp(ob[list[i]][j]) 
)<br/>　　　　　　　　{<br/>　　　　　　　　　　ob[list[i]][j] = 
make_inventory(list[i]);<br/>　　　　　　　　　　continue;<br/>　　　　　　　　}<br/>　　　　　　　　if( 
environment(ob[list[i]][j]) != 
this_object())<br/>　　　　　　　　{<br/>　　　　　　　　　　if(ob[list[i]][j]-&gt;is_character()<br/>　　　　　　　　　　&amp;&amp;!ob[list[i]][j]-&gt;return_home(this_object()) 
)<br/>　　　　　　　　　　add(&quot;no_clean_up&quot;, 1);<br/>　　　　　　　　}<br/>　　　　　　}<br/><span style="color:#006666">//这里其实与物件只有一个是一样的，只是因为相同的物品不止一个，需要进行几次的循环判断而已。</span><br/><br/>　　　　 
}<br/>　　}<br/>　　set_temp(&quot;objects&quot;, ob);<br/><span style="color:#006666">//看到这里，知道这个函数里ob映射集是如何来的了吧，实际上ob_list就是代表的这个房间里的的query(&quot;objects&quot;)，是一个字符串内容的映射集，而ob就是代表的这个房间里的query_temp(&quot;objects&quot;)它实际上一个object型的映射集。<br/></span>}</p><p style="text-align:left;">　　reset()函数结束了，其实在ROOM里，除了这两个函数，还有一个在一开始编译进内存后进行首次调用reset()函数的setup()函数之外，其它的函数都是有关门的，都是可以去掉并影响房间的主要功能的，ROOM标准继承的最主要功能就是定时检查自己房间里的物品是否还在？是否需要更新等等。而这个定时则就是由MUDOS定义并按时呼叫房间里的reset()，这个时间绝大多数被定义为十五分钟。<br/>　　我们通过上面的程序详解可以看出，当一个房间被编译成功进入内存之后，那么这个房间就将自身产生出来的各个物体（假如它有的话）记入一个query_temp(&quot;objects&quot;)的物件映射变量中，这个变量与我们写程序里的query(&quot;objects&quot;)是一一对应的，只不过query(&quot;objects&quot;)里记的是这此物件的<br/>文件路径，而query_temp(&quot;objects&quot;)里记的是这些具体的物件。关于这两个映射的区别，有兴趣的新巫师可以找一个有很多NPC的房间按下面分别call两次，看看区别：<br/>call 
here-&gt;query(&quot;objects&quot;)<br/>call here-&gt;query_temp(&quot;objects&quot;)</p><p style="text-align:left;">　　在reset()被调用时，程序就会循环地一个个地查找这些物件是否还在MUD中？如果这些物件都已经不存在了，那么，reset()函数就会通过呼叫make_inventory()函数将其再次制造出来，也就是我们看到了，更新时间一到，很多被杀死的NPC，用掉的东西都会在原处产生出来。<br/>　　而如果这些物件都还在MUD中，就会检查它们是否还在原处？如果不在的话，只要是生物，就呼叫它的return_home()函数（这个函数在所有NPC的标准继承<br/>/inherit/char/npc.c里），叫它回来。并且要把这个房间作为参数传递过去，否则NPC会回不来。如果不是生物只得作罢（这就是房间产生出的物品如果被某一玩家放在身上，就再也不能重生的原因）。那么下面我们就来看一下npc.c里的return_home()函数：</p><p style="text-align:left;">int return_home(object home)<br/><span style="color:#006666">//注意，括号里的home就是呼叫它回家的那个房间，当时是叫this_object()</span><br/>{<br/>　　if( 
!environment()|| environment()==home ) return 1;<br/><span style="color:#006666">//再次检查：是否在一个存在的环境里？是否已经回来了？如果是，则什么也不做，返回！<br/></span>　　if( 
!living(this_object())|| is_fighting()) return 0;<br/><span style="color:#006666">//如果NPC处于昏迷或战斗状态，则不回来，返回值是0,综合room.c，原房间会增加no_clean_up记号;<br/></span>　　message(&quot;vision&quot;, 
this_object()-&gt;name() + &quot;急急忙忙地离开了。\n&quot;,environment(), 
this_object());<br/>　　return move(home);<br/>}</p><p style="text-align:left;">　　谈到这里，大家可以发现，所谓房间的更新，实际上只是房间里的物体进行更新，这个房间没有任的变化。也就是说，如果在房间更新的时候，我们站在这个房间里，或者我们扔了一个不属于任何房的物品在这个房间里，都不会受到影响，这些物品与我们在更新前后都不会消失。这个与我们巫师进update 
here是本质性的两回事（updata here就是更新了房间）。</p><p style="text-align:left;">　　那么，有时有的玩家就会说，我曾得到一个很好的宝物，离线不能保存，我就把它扔在一个很少有去的地方，结果，每次再去连线再去找的时候，大多数时候都找不到，不会是被别人捡去吧？这里就及到另一个概念：MUD里的资源清除。<br/>　<br/>　　大家知道，在LPMUD里，所有的程序都必须装载进内存里才会工作。因此，MUD的内存资源便就是最主要的资源。更合理地分配和使用内存便成为一个MUD效率高低的体现。<br/>　　MUDOS为了节约内存的耗用，对于每一个占用内存的对象，包括是房间、物品、人物、指令等等，如果相当长的时间内没有被其它程序参考到（参考的含义：就是包括别人进入、看到、或者使用到这个房间、物品、或指令，还包括各个程序等等）的话，也就是这个对象很长时间没有活动了，MUDOS就会调用这个对象的clean_up()函数（由于大多数的程序都会继承这个函数标准文件），如果该函数返回1，则下次同样情况还会调用该对象的clean_up；如果返回0，则永远不再调用。那么，我们就来看一下/feature/下面的clean_up.c文件，这个文件只有一个函数：</p><p style="text-align:left;">int clean_up()<br/>{<br/>　　object *inv;<br/>　　int i;</p><p style="text-align:left;">　　if( !clonep() &amp;&amp; this_object()-&gt;query(&quot;no_clean_up&quot;) 
)<br/>　　　　return 1;<br/><span style="color:#006666">//如果这个对象不是clone出来并且有&quot;no_clean_up&quot;记号的，则返回1（返回1的含义上面说过了）</span></p><p style="text-align:left;">　　if(interactive(this_object())) return 1;<br/><span style="color:#006666">//如果对象是互动物件，比如玩家，就返回1</span></p><p style="text-align:left;">　　if(environment()) return 1;<br/><span style="color:#006666">//如果对象处在一个环境里，也返回1</span></p><p style="text-align:left;">　　inv = all_inventory();<br/><span style="color:#006666">//取出这个对象里面所有的物件</span><br/>　　for(i=sizeof(inv)-1; i&gt;=0; 
i--)<br/>　　if(interactive(inv[i])) return 1;<br/><span style="color:#006666">//循环检查这些物件，只要其中有一个互动物件，就返回1</span></p><p style="text-align:left;">　　destruct(this_object());<br/>　　return 0;<br/><span style="color:#006666">//全部检查完了后，就决定正式摧毁自身，释放出这个对象所占用的内存，并返回0</span><br/>}</p><p style="text-align:left;">　　我们再次复习一下clean_up()函数返回1的含义，如果clean_up()函数返回1，则MUDOS在这一次的调用时不会做其的任何举动，但到了下一次想调用的时间里，还将再次调用这个对象的clean_up()函数。那么从这可以看出，有以下四种情况不会将其清除出内存：<br/>一、非clone出来并且有no_clean_up参数的对象；<br/>二、玩家永远不会<br/>三、处于一个还存在的环境里<br/>四、自己里面存在着玩家<br/>　　也就是MUDOS定时摧毁内存不需要的对象是由外向内的，比如一个房间，系统只要检查这个房间里没有no_clean_up参数、里面没有玩家就可清除它，而房间里的物品、NPC都会因环境的不存在而消失。这个清除的定时时间一般都为两个小时。当然要视不同的MUDOS里的设置而看的。<br/>　　再说一点题外话，如果一个房间长时间没有玩家走进来，当然会被MUDOS清出内存，而突然又有玩家进来呢？很简单，它会在一瞬间被编译进内存，进入一个已经存在在内存里的房间与进入一个刚刚编译出来进入内存的房间对于我们的玩家来说，是察觉不出它们之间的差异的。　 &nbsp;</p>]]></description><category>Mud</category><comments>http://www.xiaqiang.com.cn/post/19.html#comment</comments><wfw:commentRss>http://www.xiaqiang.com.cn/feed.asp?cmt=19</wfw:commentRss></item><item><title>Hash table在MudOS中的实现</title><author>null@null.com (xiaqiang)</author><link>http://www.xiaqiang.com.cn/post/17.html</link><pubDate>Fri, 22 Jan 2016 18:58:31 +0800</pubDate><guid>http://www.xiaqiang.com.cn/post/17.html</guid><description><![CDATA[<p><strong>Hash table在MudOS中的实现</strong>来源网络，如有侵权请告知，即处理！</p><p><br/></p><p>&nbsp;&nbsp;&nbsp; 本文介绍了 MudOS中使用的散 列函数，并对包装了散列函数的散 列表寻址操作做了一个简单的分析，最后模拟MudOS中object hash table实现了一个简 化的散列表。</p><p>&nbsp;&nbsp;&nbsp; 在MudOS中，散列 表的应用非常广泛，可以说凡是用到查找的地方都用到了散列（hash table），散列的好处在于它的 效率，理想状态下，搜索、插入、删除操作的时间均为O(1)，在应用中，虽然达不到这样的理想状态，但相 比于其它数据结构来说，hash table的优势还是很明显的。在非理想状态下，不可避免的会遇到碰撞 问题（collision），MudOS源码中处理碰撞 所采用的方法是使用链表散列。</p><h3>散列函数（hash function）</h3><p>&nbsp;&nbsp;&nbsp; 在最新发布的MudOS源码（v22.2b14）中，散列函数（hash function）定义于hash.c：</p><p>/* hash.c */</p><p>/*</p><p>** A simple and fast generic string hasher based on Peter K. &nbsp;Pearson&#39;s</p><p>** article in CACM 33-6, pp. 677.</p><p>*/</p><p>#define EDIT_SOURCE</p><p>#define NO_SOCKETS</p><p>#define NO_OPCODES</p><p>#include &quot;std.h&quot;</p><p>static int T[] =</p><p>{</p><p>&nbsp;&nbsp;&nbsp; 1, 87, 49, 12, 176, 178, 102, 166, 121, 193, 6, 84, 249, &nbsp;230, 44, 163,</p><p>&nbsp;&nbsp;&nbsp; 14, 197, 213, 181, 161, 85, 218, 80, 64, 239, 24, 226, &nbsp;236, 142, 38, 200,</p><p>&nbsp;&nbsp;&nbsp; 110, 177, 104, 103, 141, 253, 255, 50, 77, 101, 81, 18, &nbsp;45, 96, 31, 222,</p><p>&nbsp;&nbsp;&nbsp; 25, 107, 190, 70, 86, 237, 240, 34, 72, 242, 20, 214, 244, 227, 149, 235,</p><p>&nbsp;&nbsp;&nbsp; 97, 234, 57, 22, 60, 250, 82, 175, 208, 5, 127, 199, 111, &nbsp;62, 135, 248,</p><p>&nbsp; 174, 169, 211, 58, 66, 154, 106, 195, 245, 171, 17, 187, &nbsp;182, 179, 0, 243,</p><p>&nbsp;132, 56, 148, 75, 128, 133, 158, 100, 130, 126, 91, 13, 153, &nbsp;246, 216, 219,</p><p>&nbsp;&nbsp;&nbsp; 119, 68, 223, 78, 83, 88, 201, 99, 122, 11, 92, 32, 136, &nbsp;114, 52, 10,</p><p>&nbsp;&nbsp;&nbsp; 138, 30, 48, 183, 156, 35, 61, 26, 143, 74, 251, 94, 129, &nbsp;162, 63, 152,</p><p>&nbsp;&nbsp;&nbsp; 170, 7, 115, 167, 241, 206, 3, 150, 55, 59, 151, 220, 90, &nbsp;53, 23, 131,</p><p>&nbsp;&nbsp;&nbsp; 125, 173, 15, 238, 79, 95, 89, 16, 105, 137, 225, 224, &nbsp;217, 160, 37, 123,</p><p>&nbsp;&nbsp;&nbsp; 118, 73, 2, 157, 46, 116, 9, 145, 134, 228, 207, 212, 202, 215, 69, 229,</p><p>&nbsp;&nbsp;&nbsp; 27, 188, 67, 124, 168, 252, 42, 4, 29, 108, 21, 247, 19, &nbsp;205, 39, 203,</p><p>&nbsp;233, 40, 186, 147, 198, 192, 155, 33, 164, 191, 98, 204, 165, 180, 117, 76,</p><p>&nbsp;&nbsp;&nbsp; 140, 36, 210, 172, 41, 54, 159, 8, 185, 232, 113, 196, &nbsp;231, 47, 146, 120,</p><p>&nbsp;&nbsp;&nbsp; 51, 65, 28, 144, 254, 221, 93, 189, 194, 139, 112, 43, 71, 109, 184, 209,</p><p>};</p><p>INLINE int</p><p>hashstr P3(char *, s,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* string to hash */</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int, maxn,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* maximum number of chars to consider */</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int, hashs)</p><p>{</p><p>&nbsp;&nbsp;&nbsp; register unsigned int h;</p><p>&nbsp;&nbsp;&nbsp; register unsigned char *p;</p><p>&nbsp;&nbsp;&nbsp; h = (unsigned char) *s;</p><p>&nbsp;&nbsp;&nbsp; if (h) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (hashs &gt; 256) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; register int oh = T[(unsigned char) *s];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (p = (unsigned char *) s + 1; *p</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; p &lt;= (unsigned char *) s + maxn; p++) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; h = T[h ^ *p];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oh = T[oh ^ *p];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; h |= (oh &lt;&lt; 8);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (p = (unsigned char *) s + 1; *p</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; p &lt;= (unsigned char *) s + maxn; p++)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; h = T[h ^ *p];</p><p>&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp; return (int) (h % hashs);</p><p>}</p><p>/*</p><p>&nbsp;* whashstr is faster than hashstr, but requires an even &nbsp;power-of-2 table size</p><p>&nbsp;* Taken from Amylaars driver.</p><p>&nbsp;*/</p><p>INLINE int</p><p>whashstr P2(char *, s, int, maxn)</p><p>{</p><p>&nbsp;&nbsp;&nbsp; register unsigned char oh, h;</p><p>&nbsp;&nbsp;&nbsp; register unsigned char *p;</p><p>&nbsp;&nbsp;&nbsp; register int i;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!s)return 0;</p><p>&nbsp;&nbsp;&nbsp; if (!*s)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;</p><p>&nbsp;&nbsp;&nbsp; p = (unsigned char *) s;</p><p>&nbsp;&nbsp;&nbsp; oh = T[*p];</p><p>&nbsp;&nbsp;&nbsp; h = (*(p++) + 1) &amp; 0xff;</p><p>&nbsp;&nbsp;&nbsp; for (i = maxn - 1; *p &amp;&amp; --i &gt;= 0; ) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oh = T[oh ^ *p];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; h = T[h ^ *(p++)];</p><p>&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp; return (oh &lt;&lt; 8) + h;</p><p>}</p><p>注释中说明这两个函数基于Pearson发表的一篇 文章，这篇文章发表于Communications of the ACM archive Volume 33, &nbsp;Issue 6 (June 1990)，文章题目是: Fast hashing of &nbsp;variable-length text strings。whashstr函数取自于Amylaars driver——另一个mud driver？ 这个函数比第一个函数hashstr速度要快一点，因此在MudOS中 全部采用whashstr函数来实现散列表。</p><p>我并没有找到Pearson的那篇文章，对于数组T[]的产生也就无从得知，在查找资料（参 考资料3）时找到另一个产生的T的算法和一个散列函数：</p><p>&nbsp; -- use an array of 256 1-byte values</p><p>&nbsp; ub1 x[0..255];</p><p>&nbsp; -- fill it with the values 0 to 255 in some &nbsp;pseudorandom order</p><p>&nbsp; -- (this is derived from the alleged RC4)</p><p>&nbsp; { for i in 0..255 do</p><p>&nbsp;&nbsp;&nbsp; { x[i] := i;</p><p>&nbsp;&nbsp;&nbsp; }</p><p>&nbsp; }</p><p>&nbsp; k=7;</p><p>&nbsp; { for j in 0..3 do</p><p>&nbsp;&nbsp;&nbsp; { for i in 0..255 do</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { s = x[i];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; k = (k + s) mod 256;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x[i] = x[k];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x[k] = s;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp; }</p><p>&nbsp; }</p><p>&nbsp; -- use the length of the message to initialize the &nbsp;hash</p><p>&nbsp; -- XXX can be 0, or some constant, or some argument</p><p>&nbsp; hash := (XXX+len) mod 256;</p><p>&nbsp; -- hash the characters in the message one byte at a &nbsp;time</p><p>&nbsp; {for i in 0..len-1 do</p><p>{hash := (hash + &nbsp;message[i]) mod 256;&nbsp; hash := x[hash];}}</p><p>将生成T的算法写成c函数：</p><p>void gen_T(int* vec)</p><p>{</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i, j, s, k = 7;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; 256; ++i)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vec[i] = i;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (j = 0; j &lt; 4; ++j)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; 256; ++i)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s = vec[i];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; k = (k + s) % 256;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vec[i] = vec[k];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vec[k] = s;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>}</p><p>于是，我们有 了另一个散列函数：</p><p>static int simulate_T[] =</p><p>{</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;49,118,63,252,13,155,114,130,137,40,210,62,219,246,136,221,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;174,106,37,227,166,25,139,19,204,212,64,176,70,11,170,58,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;146,24,123,77,184,248,108,251,43,171,12,141,126,41,95,142,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;167,46,178,235,30,75,45,208,110,230,226,50,32,112,156,180,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;205,68,202,203,82,7,247,217,223,71,116,76,6,31,194,183,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;15,102,97,215,234,240,53,119,52,47,179,99,199,8,101,35,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;65,132,154,239,148,51,216,74,93,192,42,86,165,113,89,48,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;100,195,29,211,169,38,57,214,127,117,59,39,209,88,1,134,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;92,163,0,66,237,22,164,200,85,9,190,129,111,172,231,14,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;181,206,128,23,187,73,149,193,241,236,197,159,55,125,196,60,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;161,238,245,94,87,157,122,158,115,207,17,20,145,232,107,16,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;21,185,33,225,175,253,81,182,67,243,69,220,153,5,143,3,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;26,213,147,222,105,188,229,191,72,177,250,135,152,121,218,44,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;120,140,138,28,84,186,198,131,54,2,56,78,173,151,83,27,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;255,144,249,189,104,4,168,98,162,150,254,242,109,34,133,224,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;228,79,103,201,160,90,18,61,10,233,91,80,124,96,244,36&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p><p>};</p><p>int simulate_hashstr(char * s, int len)</p><p>{</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int h = len % 256;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; len; ++i)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; h = (h + s[i]) % 256;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; h = simulate_T[h];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return h;</p><p>}</p><p>显然，这个散 列函数生成的值在0~255之间。</p><p>处理字符串的散列函数还有很多，详见参 考资料3。</p><h3>使用散列函数寻址</h3><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在MudOS源码（v22.2b14）中，定义了5个宏或函数分别处理应用中的各个散列表的寻址操作，这些宏包装了whashstr函数以方便使用：</p><p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p><p>/* lex.h */</p><p>#define DEFHASH 64</p><p>#define defhash(s) (whashstr((s), 10) &amp; (DEFHASH - 1))</p><p>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p><p>/* lex.c */</p><p>#define IDENT_HASH_SIZE 1024</p><p>#define IdentHash(s) (whashstr((s), 20) &amp; (IDENT_HASH_SIZE - 1))</p><p>3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p><p>/* object.c */</p><p>/* CFG_LIVING_HASH_SIZE定义于 options.h</p><p>&nbsp;&nbsp; #define CFG_LIVING_HASH_SIZE&nbsp;&nbsp;&nbsp;&nbsp; 256 */</p><p>INLINE_STATIC int hash_living_name P1(char *, str)</p><p>{</p><p>&nbsp;&nbsp;&nbsp; return whashstr(str, 20) &amp; (CFG_LIVING_HASH_SIZE - 1);</p><p>}</p><p>4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p><p>/* otable.c */</p><p>#define ObjHash(s) whashstr(s, 40) &amp; otable_size_minus_one</p><p>5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p><p>/* stralloc.c */</p><p>#define StrHash(s) (whashstr((s), 20) &amp; (htable_size_minus_one))</p><p>&nbsp;&nbsp;&nbsp; 对于1、2、3，参数和 函数功能已经很明显：萃取（extract）低位字节作为被评估（evaluated） 的字符串所在散列表的位置，对应的散列表的大小为DEFHASH，IDENT_HASH_SIZE，CFG_LIVING_HASH_SIZE，由于使用的“&amp;” 操作（按位与）来萃取低位字节，因此，需要将这些散列表的大小置为2的指数。</p><p>&nbsp;&nbsp;&nbsp; 对于第4个宏，参数otable_size_minus_one在 otable.c中 被赋值。</p><p>/* otable.c */</p><p>/*</p><p>&nbsp;* hash table - list of pointers to heads of object chains.</p><p>&nbsp;* Each object in chain has a pointer, next_hash, to the next object.</p><p>&nbsp;*/</p><p>static object_t **obj_table = 0;</p><p>void init_otable()</p><p>{</p><p>&nbsp;&nbsp;&nbsp; int x, y;</p><p>&nbsp;&nbsp;&nbsp; /* ensure that &nbsp;otable_size is a power of 2 */</p><p>&nbsp;&nbsp;&nbsp; y = OTABLE_SIZE;</p><p>&nbsp;&nbsp;&nbsp; for (otable_size = 1; otable_size &lt; y; otable_size *= 2)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;</p><p>&nbsp;&nbsp;&nbsp; otable_size_minus_one = otable_size - 1;</p><p>&nbsp;&nbsp;&nbsp; obj_table = CALLOCATE(otable_size, object_t *,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; TAG_OBJ_TBL, &quot;init_otable&quot;);</p><p>&nbsp;&nbsp;&nbsp; for (x = 0; x &lt; otable_size; x++)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj_table[x] = 0;</p><p>}</p><p>&nbsp;&nbsp;&nbsp; 宏OTABLE_SIZE的功能为存储配置文件中object table size的值，在MudOS启动时，在main函数里调用读取配置文件的函数，对OTABLE_SIZE进 行赋值，在init_otalbe函数中将这个值调整为2的 指数，并将这个值赋给otable_size_minus_one。</p><p>&nbsp;&nbsp;&nbsp; 对于第5个宏，htable_size_minus_one的 赋值过程与otable_size_minus_one大同小异。但是在查看某个mudlib的配置文件时发现下面的问题：</p><p>/* 取自config.xxx */</p><p># Define &nbsp;the size of the shared string hash table.&nbsp; This number should</p><p># a prime, probably between 1000 and 30000; if you set it to about 1/5</p><p># of the &nbsp;number of distinct strings you have, you will get a hit ratio</p><p># (number &nbsp;of comparisons to find a string) very close to 1, as found strings</p><p># are &nbsp;automatically moved to the head of a hash chain.&nbsp; You will never</p><p># need &nbsp;more, and you will still get good results with a smaller table.</p><p>hash table size : 7001</p><p>&nbsp;&nbsp;&nbsp; 注释中（以#开头的语句），说明hash table size必须为质数（prime），然而源代 码中却需要保证这个值为2的指数。我想出现前后矛盾的原因大概和MudOS版 本差异有关：比较早的版本使用的是hashstr 函数 ，这个函数在后续的寻址操作中用的是“%” 求模运算，而使用质数作为hash table的大小在解决碰撞的效率上要好些（猜测如此，未经求证），因此这些mudlib的config文件就一直沿用这些传统；目前比较新的MudOS版本采用的是whashstr 函数，其后续的寻址操作——正如之前介绍的，用的是“&amp;”按位与运算，这 必然要求hash table的大小必须为2的指数。</p><h3>散列表的实现</h3><p>&nbsp;&nbsp;&nbsp; 有了前面分析的散列函数和宏，本文将以object table为 例，来实现一个hash table，object table实 现的源码参见最新发布的MudOS源码 （v22.2b14）中的otable.c。下面这些代码与源码有差异，这么做的 原因是为了不牵涉到具体应用，而仅仅是单纯的实现一个hash table。</p><p>/* hashtable.h */</p><p>#if !defined(_HASH_TABLE_H_)</p><p>#define _HASH_TABLE_H_</p><p>#define STRING_SIZE 64</p><p>typedef struct object_s {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char name[STRING_SIZE];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct object_s *next_hash;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char value[STRING_SIZE];</p><p>} object_t;</p><p>void init_otable();</p><p>void clear_otable();</p><p>void enter_object_hash(object_t *);</p><p>void remove_object_hash(object_t *);</p><p>object_t *lookup_object_hash(char *);</p><p>void dump();</p><p>#endif&nbsp;&nbsp;&nbsp;&nbsp; // _HASH_TABLE_H_</p><p>/* hashtable.c */</p><p>#include &quot;stdafx.h&quot;</p><p>#include &quot;stdlib.h&quot;</p><p>#include &quot;stdio.h&quot;</p><p>#include &quot;string.h&quot;</p><p>#include &quot;hashtable.h&quot;</p><p>#define BUCKET_SIZE 256&nbsp;&nbsp;&nbsp;&nbsp;</p><p>static int otable_size;</p><p>static int otable_size_minus_one;</p><p>int whashstr(char *, int);</p><p>#define ObjHash(s) whashstr((char *)s, 40) &amp; otable_size_minus_one</p><p>/*</p><p>* hash table - list of &nbsp;pointers to heads of object chains.</p><p>* Each object in chain &nbsp;has a pointer, next_hash, to the next object.</p><p>*/</p><p>static object_t **obj_table = 0;</p><p>void init_otable()</p><p>{</p><p>&nbsp;&nbsp;&nbsp; int y;</p><p>&nbsp;&nbsp;&nbsp; /* ensure that &nbsp;otable_size is a power of 2 */</p><p>&nbsp;&nbsp;&nbsp; y = BUCKET_SIZE;</p><p>&nbsp;&nbsp;&nbsp; for (otable_size = 1; otable_size &lt; y; otable_size *= 2)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;</p><p>&nbsp;&nbsp;&nbsp; otable_size_minus_one = otable_size - 1;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* by using calloc, &nbsp;each element in obj_table is initialized to 0 */</p><p>&nbsp;&nbsp;&nbsp; obj_table = (object_t **)calloc(otable_size, sizeof(object_t *));</p><p>}</p><p>void clear_otable()</p><p>{</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; free(obj_table);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; BUCKET_SIZE; ++i) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj_table[i] = 0;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>}</p><p>/* A global. */</p><p>static int h;</p><p>/*</p><p>* Looks for obj in &nbsp;table, moves it to head.</p><p>*/</p><p>object_t *find_obj_n(char * s)</p><p>{</p><p>&nbsp;&nbsp;&nbsp; object_t *curr, *prev;</p><p>&nbsp;&nbsp;&nbsp; h = ObjHash(s);</p><p>&nbsp;&nbsp;&nbsp; curr = obj_table[h];</p><p>&nbsp;&nbsp;&nbsp; prev = 0;</p><p>&nbsp;&nbsp;&nbsp; while (curr) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!strcmp(curr-&gt;name, s)) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* found it */</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (prev) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* not at head of list */</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prev-&gt;next_hash = curr-&gt;next_hash;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curr-&gt;next_hash = obj_table[h];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj_table[h] = curr;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (curr);&nbsp; /* pointer to object */</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prev = curr;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curr = curr-&gt;next_hash;</p><p>&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp; return (0);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* not &nbsp;found */</p><p>}</p><p>/*</p><p>* Add an object to the &nbsp;table - can&#39;t have duplicate names.</p><p>*/</p><p>void enter_object_hash(object_t * ob)</p><p>{</p><p>&nbsp;&nbsp;&nbsp; object_t *s;</p><p>&nbsp;&nbsp;&nbsp; s = find_obj_n(ob-&gt;name); /* This sets h */</p><p>&nbsp;&nbsp;&nbsp; ob-&gt;next_hash = obj_table[h];</p><p>&nbsp;&nbsp;&nbsp; obj_table[h] = ob;</p><p>&nbsp;&nbsp;&nbsp; return;</p><p>}</p><p>/*</p><p>* Remove an object from the table - generally called when it</p><p>* is removed from the &nbsp;next_all list - i.e. in destruct.</p><p>*/</p><p>void remove_object_hash(object_t * ob)</p><p>{</p><p>&nbsp;&nbsp;&nbsp; object_t *s;</p><p>&nbsp;&nbsp;&nbsp; s = find_obj_n(ob-&gt;name); /* this sets h, and &nbsp;cycles the ob to the front */</p><p>&nbsp;&nbsp;&nbsp; obj_table[h] = ob-&gt;next_hash;</p><p>&nbsp;&nbsp;&nbsp; ob-&gt;next_hash = 0;</p><p>&nbsp;&nbsp;&nbsp; return;</p><p>}</p><p>/*</p><p>* Lookup an object in &nbsp;the hash table; if it isn&#39;t there, return null.</p><p>* This is only &nbsp;different to find_object_n in that it collects different</p><p>* stats; more finds are actually done than the user ever asks for.</p><p>*/</p><p>object_t *lookup_object_hash(char * s)</p><p>{</p><p>&nbsp;&nbsp;&nbsp; return find_obj_n(s);</p><p>}</p><p>/*</p><p>* Display the sum of &nbsp;elements in obj_table.</p><p>*/</p><p>void dump()</p><p>{</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i, count;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object_t * curr;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; BUCKET_SIZE; ++i) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; count = 0;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curr = obj_table[i];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (curr) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++count;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curr = curr-&gt;next_hash;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf(&quot;%d\n&quot;, count);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>}</p><p>/* Hash function. */</p><p>static int T[] =</p><p>{</p><p>&nbsp;&nbsp;&nbsp; 1, 87, 49, 12, 176, 178, 102, 166, 121, 193, 6, 84, 249, 230, 44, 163,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 14, 197, &nbsp;213, 181, 161, 85, 218, 80, 64, 239, 24, 226, 236, 142, 38, 200,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 110, 177, 104, 103, 141, 253, 255, 50, 77, 101, 81, 18, 45, 96, 31, 222,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 25, 107, &nbsp;190, 70, 86, 237, 240, 34, 72, 242, 20, 214, 244, 227, 149, 235,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 97, 234, &nbsp;57, 22, 60, 250, 82, 175, 208, 5, 127, 199, 111, 62, 135, 248,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 174, 169, 211, 58, 66, 154, 106, 195, 245, 171, 17, 187, 182, 179, 0, 243,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 132, 56, &nbsp;148, 75, 128, 133, 158, 100, 130, 126, 91, 13, 153, 246, 216, 219,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 119, 68, &nbsp;223, 78, 83, 88, 201, 99, 122, 11, 92, 32, 136, 114, 52, 10,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 138, 30, &nbsp;48, 183, 156, 35, 61, 26, 143, 74, 251, 94, 129, 162, 63, 152,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 170, 7, &nbsp;115, 167, 241, 206, 3, 150, 55, 59, 151, 220, 90, 53, 23, 131,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 125, 173, 15, 238, 79, 95, 89, 16, 105, 137, 225, 224, 217, 160, 37, 123,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 118, 73, &nbsp;2, 157, 46, 116, 9, 145, 134, 228, 207, 212, 202, 215, 69, 229,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 27, 188, &nbsp;67, 124, 168, 252, 42, 4, 29, 108, 21, 247, 19, 205, 39, 203,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 233, 40, &nbsp;186, 147, 198, 192, 155, 33, 164, 191, 98, 204, 165, 180, 117, 76,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 140, 36, &nbsp;210, 172, 41, 54, 159, 8, 185, 232, 113, 196, 231, 47, 146, 120,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 51, 65, &nbsp;28, 144, 254, 221, 93, 189, 194, 139, 112, 43, 71, 109, 184, 209,</p><p>};</p><p>int whashstr(char * s, int maxn)</p><p>{</p><p>&nbsp;&nbsp;&nbsp; register unsigned char oh, h;</p><p>&nbsp;&nbsp;&nbsp; register unsigned char *p;</p><p>&nbsp;&nbsp;&nbsp; register int i;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!s)return 0;</p><p>&nbsp;&nbsp;&nbsp; if (!*s)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;</p><p>&nbsp;&nbsp;&nbsp; p = (unsigned char *) s;</p><p>&nbsp;&nbsp;&nbsp; oh = T[*p];</p><p>&nbsp;&nbsp;&nbsp; h = (*(p++) + 1) &amp; 0xff;</p><p>&nbsp;&nbsp;&nbsp; for (i = maxn - 1; *p &amp;&amp; --i &gt;= 0; ) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oh = T[oh ^ *p];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; h = T[h ^ *(p++)];</p><p>&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp; return (oh &lt;&lt; 8) + h;</p><p>}</p><p>这份代码实现了一个hashtable的基本操作：插入，删除，查找。为了测试这个hashtable， 我写了一份非常简单的测试代码，测试数据取自于http://www.graphcomp.com/info/mud/mu<a href="http://biancheng.dnbcw.info/dos/">dos</a>/History_MudOS.html，为了简化代码，我用<a href="http://biancheng.dnbcw.info/python/">python</a>对这篇文章进行 了一下处理，首先保存这篇文章的内容为: history_mu<a href="http://biancheng.dnbcw.info/dos/">dos</a>.txt，我把它存放在E盘根目录，<a href="http://biancheng.dnbcw.info/python/">python</a>处理源码如下：</p><p># &nbsp;preread.py</p><p>import re</p><p>def foo &nbsp;():</p><p>&nbsp;&nbsp;&nbsp; rex = &nbsp;re.compile(&#39;[A-Za-z0-9]+&#39;)</p><p>&nbsp;&nbsp;&nbsp; f = &nbsp;open(&#39;e:\out.txt&#39;,&#39;w&#39;)</p><p>&nbsp;&nbsp;&nbsp; for &nbsp;line in open(&#39;e:\histroy_mudos.txt&#39;,&#39;r&#39;):</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;for word in rex.findall(line):</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f.write(word)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f.write(&#39;\n&#39;)</p><p>在python控 制台下运行这些代码，获得处理过的文件out.txt，out.txt中 将包含history_mudos.txt中的所有单词，每个单词按行排列。有了经过预处理的out.txt，编写测试代码就简单得多了，为了更加简化操作，下面的代码将使用c++来 编写：</p><p>/* main.cpp */</p><p>#include &lt;iostream&gt;</p><p>#include &lt;fstream&gt;</p><p>#include<algorithm></algorithm></p><p>#include &lt;string&gt;</p><p>#include &lt;vector&gt;</p><p>#include &lt;set&gt;</p><p>#include &quot;hashtable.h&quot;</p><p>using namespace std;</p><p>static vector&lt;object_t *&gt; ob_table;</p><p>struct constructor {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; operator () (const string&amp; str)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object_t * pob = new object_t;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcpy(pob-&gt;name, str.c_str());</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcpy(pob-&gt;value, strupr(const_cast&lt;char*&gt;(str.c_str())));</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pob-&gt;next_hash = 0;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ob_table.push_back(pob);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>};</p><p>struct destructor {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; operator () (object_t * pob)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete pob;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pob = 0;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>};</p><p>struct ob_inserter {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; operator () (object_t * pob)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enter_object_hash(pob);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>};</p><p>void create()</p><p>{</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifstream infile;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string str;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; infile.open(&quot;E:\\out.txt&quot;);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set&lt;string&gt; word_set;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (getline(infile, str)) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; word_set.insert(str);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for_each(word_set.begin(), word_set.end(), constructor());</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; infile.close();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; init_otable();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for_each(ob_table.begin(), ob_table.end(), ob_inserter());</p><p>}</p><p>void clear()</p><p>{</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for_each(ob_table.begin(), ob_table.end(), destructor());</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clear_otable();</p><p>}</p><p>void lookup(char* s)</p><p>{</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object_t * pob = lookup_object_hash(s);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (pob)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; pob-&gt;value &lt;&lt; endl;</p><p>}</p><p>int main(void)</p><p>{</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; create();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lookup(&quot;the&quot;);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lookup(&quot;history&quot;);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lookup(&quot;of&quot;);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lookup(&quot;MudOS&quot;);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dump();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clear();</p><p>}</p><p>编译运行，结果如下：</p><p>THE</p><p>OF</p><p>MUDOS</p><p>dump函数统计个数见下图，总共651个点，对于散列大 小为256而言，这样的分布还是满足要求的。</p><p><a href="http://img.dnbcw.info/2011118/smki3042860.jpg" target="_blank"><img width="600" alt="" src="http://img.dnbcw.info/2011118/smki3042860.jpg" border="0"/></a></p><p>结果证明这份hash table的实现代码是正确的。</p><p>参考资料：</p><p>[1]&nbsp;&nbsp;&nbsp; Sartaj &nbsp;Sahni. Data Structures, Algorithms, and Applications in C++</p><p>[2]&nbsp;&nbsp;&nbsp; 侯捷. 《STL源码分析》</p><p>[3]&nbsp;&nbsp;&nbsp; http://burtleburtle.net/bob/hash/index.html</p><p>[4]&nbsp;&nbsp;&nbsp; http://www.mudos.org/</p><p><br/></p>]]></description><category>Mud</category><comments>http://www.xiaqiang.com.cn/post/17.html#comment</comments><wfw:commentRss>http://www.xiaqiang.com.cn/feed.asp?cmt=17</wfw:commentRss></item><item><title>fluffos 3.0（alpha9.0） local_options配置详细选项</title><author>null@null.com (xiaqiang)</author><link>http://www.xiaqiang.com.cn/post/16.html</link><pubDate>Thu, 15 Oct 2015 11:23:13 +0800</pubDate><guid>http://www.xiaqiang.com.cn/post/16.html</guid><description><![CDATA[<p>/*<br/>&nbsp;* local_options.h: compile-time configuration of the driver<br/>&nbsp;*/</p><p>/****************************************************************************<br/>&nbsp;* EVERY time you change ANYTHING in this file, RECOMPILE from scratch.&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* (type &quot;make clean&quot; then &quot;make&quot; on a UNIX system) Failure to do so may&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* cause the driver to behave oddly.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;****************************************************************************/</p><p>/* NOTES: Many of the configurable options are now set in the runtime config.<br/>&nbsp;* <br/>&nbsp;* This file only contain a list of default settings, for quick diffing .<br/>&nbsp;* See detailed explaination from &#39;local_options.README&#39;<br/>&nbsp;*/</p><p>#ifndef _LOCAL_OPTIONS_H_<br/>#define _LOCAL_OPTIONS_H_</p><p>/****************************************************************************<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COMPAT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;****************************************************************************/<br/>#undef COMPAT_32<br/>#undef NO_ADD_ACTION<br/>#undef NO_SNOOP<br/>#undef NO_ENVIRONMENT<br/>#undef NO_WIZARDS<br/>#undef NO_SHADOWS<br/>#define NO_LIGHT<br/>#undef PRIVS<br/>#undef SENSIBLE_MODIFIERS</p><p>/****************************************************************************<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BEHAVIOR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;****************************************************************************/<br/>#define OLD_ED<br/>#undef ED_INDENT_CASE<br/>#define ED_INDENT_SPACES 4<br/>#undef RECEIVE_ED<br/>#define RESTRICTED_ED</p><p>#define DEFAULT_PRAGMAS PRAGMA_WARNINGS + PRAGMA_SAVE_TYPES + PRAGMA_ERROR_CONTEXT + PRAGMA_OPTIMIZE<br/>#define SAVE_EXTENSION &quot;.o&quot;<br/>#define SAVE_GZ_EXTENSION &quot;.o.gz&quot;</p><p>#undef USE_ICONV<br/>#undef IPV6<br/>#undef DTRACE</p><p>/****************************************************************************<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PACKAGES&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;****************************************************************************/<br/>#undef CUSTOM_CRYPT<br/>#define PACKAGE_ASYNC<br/>#define PACKAGE_COMPRESS<br/>#define PACKAGE_CONTRIB<br/>#define PACKAGE_CORE<br/>#undef PACKAGE_CRYPTO</p><p>#undef PACKAGE_DB<br/>#ifdef PACKAGE_DB<br/>#define USE_MYSQL 1<br/>#undef USE_POSTGRES<br/>#undef USE_SQLITE3<br/>#endif</p><p>#define PACKAGE_DEVELOP<br/>#undef PACKAGE_DWLIB<br/>#define PACKAGE_EXTERNAL<br/>#define PACKAGE_MATH<br/>#undef PACKAGE_MATRIX<br/>#define PACKAGE_MUDLIB_STATS<br/>#define PACKAGE_OPS<br/>#undef PACKAGE_PARSER<br/>#define PACKAGE_PCRE<br/>#define PACKAGE_SHA1<br/>#define PACKAGE_SOCKETS<br/>#define PACKAGE_TRIM<br/>#undef PACKAGE_THREAD</p><p>#define PACKAGE_UIDS<br/>#ifdef PACKAGE_UIDS<br/>#define AUTO_SETEUID<br/>#undef AUTO_TRUST_BACKBONE<br/>#endif</p><p>#endif /* _LOCAL_OPTIONS_H_ */<br/></p><p><br/></p>]]></description><category>Mud</category><comments>http://www.xiaqiang.com.cn/post/16.html#comment</comments><wfw:commentRss>http://www.xiaqiang.com.cn/feed.asp?cmt=16</wfw:commentRss></item><item><title>FluffOS 3.0 centos 编译指南 作者：夕阳－风之传说 luoyun  </title><author>null@null.com (xiaqiang)</author><link>http://www.xiaqiang.com.cn/post/15.html</link><pubDate>Sun, 14 Jun 2015 18:20:10 +0800</pubDate><guid>http://www.xiaqiang.com.cn/post/15.html</guid><description><![CDATA[<ol class=" list-paddingleft-2"><li><p>作者：夕阳－风之传说 luoyun&nbsp;&nbsp;</p></li><li><p>特别感谢sunyc和lonely的热心指导！</p></li><li><p><br/></p></li><li><p>FluffOS v3.0在win7虚拟机centos5.5 64位中编译时，需要用到的软件有gcc 4.8和libevent-2.0.21，以下是编译过程：</p></li><li><p><br/></p></li><li><p>1. 下载fluffos源代码，网址：https://github.com/fluffos/fluffos/releases</p></li><li><p><br/></p></li><li><p>2. 下载VMware中文版，作者下的版本是9.0.2；再将虚拟机需要的安装程序iso文件下载好，作者使用的是centos 5.5 64位</p></li><li><p><br/></p></li><li><p>3. 在win7系统中安装VMware，完成后新建虚拟机并登录用户名root密码就是你创建虚拟机时设置的密码，下面整个编译过程我们都用root权限来进行。</p></li><li><p><br/></p></li><li><p>4. 准备好这一切后，我们进入centos虚拟机，由于作者下载这个版本是英文版，所以进行了汉化</p></li><li><p>&nbsp;&nbsp; 汉化过程 （提示：虚拟机切换命令操作和界面操作快键为：界面Ctrl+Alt+F7，命令窗口ctrl+alt+F1-F5均可，可多开窗口）</p></li><li><p>&nbsp;&nbsp; 4.1 yum install fonts-chinese&nbsp;&nbsp;</p></li><li><p>&nbsp;&nbsp; 4.2 yum install fonts-ISO8859-2</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;4.3 cd /usr/share/fonts/</p></li><li><p>&nbsp;&nbsp; 4.4 fc-cache -fv</p></li><li><p>&nbsp;&nbsp; 4.5 OK完成之后我们可以在登录界面时选择中文显示，也可以在系统中设置system-&gt;adminstration-&gt;language-&gt;Chinese(P.R. of China) - 中文简体</p></li><li><p><br/></p></li><li><p>&nbsp;&nbsp;</p></li><li><p>5. 建立一个ftp方便我们上下传资料（当然你有U盘也可以用U盘来传输）</p></li><li><p>&nbsp;&nbsp;5.1 yum -y install vsftpd</p></li><li><p>&nbsp;&nbsp;5.2 service vsftpd restart</p></li><li><p>&nbsp;&nbsp;5.3 设置开机FTP自启动</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;chkconfig vsftpd on</p></li><li><p>&nbsp;&nbsp;5.4 查看本机IP，用于win7向虚拟机连接</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;ip addr</p></li><li><p>&nbsp;&nbsp;5.5 打开虚拟机防火墙</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;service iptables stop iptables</p></li><li><p>&nbsp;&nbsp;5.6 下载一个软件WinSCP，建立与虚拟机之间的连接</p></li><li><p>&nbsp;&nbsp;</p></li><li><p>6. 开始安装编译需要的软件gcc，注意：此软件需要安装4.8版本或以上，作者下载的是4.8版本</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;GCC-4.8 源码编译处于联网状态，执行下列命令</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;6.1 下载源代码</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;wget http://ftp.gnu.org/gnu/gcc/gcc-4.8.0/gcc-4.8.0.tar.bz2&nbsp;&nbsp;&nbsp;&nbsp;</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;6.2 解压代码</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;tar -jxvf&nbsp;&nbsp;gcc-4.8.0.tar.bz2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;6.3 下载编译的依赖文件</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp; cd gcc-4.8.0　</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;./contrib/download_prerequisites 　#该命令会自动下载mpr等等三个库的源码并配置　</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;6.4 在解压目录下建立编译输出目录：</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;cd ..</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;mkdir gcc-build-4.8.0</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;6.5&nbsp;&nbsp;进入编译输出目录上执行下面命令，生成编译的makefile文件等：</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;cd&nbsp;&nbsp;gcc-build-4.8.0</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;../gcc-4.8.0/configure --enable-checking=release --enable-languages=c,c++ --disable-multilib</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;6.6 执行编译命令（#在8核的虚拟机上进行编译,每个核分配2个编译任务,大约12分钟）</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;make -j16</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;注意(make -j4是指开4线程)</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;make&nbsp;&nbsp;install</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;编译过程CPU 核基本100%占用，作者cpu i5联想Y470笔记本整个编译用了2个多小时。</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;6.7 检查gcc版本</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;[root@dev02 gcc-build-4.8.0]# gcc -v</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;gcc (GCC) 4.8.0</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;</p></li><li><p>7. 安装libevent-2.0.21-stable</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;7.1.下载安装包</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;下载https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;7.2 解压</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;tar zxvf libevent-2.0.21-stable.tar.gz</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;7.3 进入目录</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;cd libevent-2.0.21-stable</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;7.4 设置安装路径</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;./configure –prefix=/usr</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;7.5 编译</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;make</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;7.6 安装</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;make install</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;</p></li><li><p>8. 用ftp连接到虚拟机，并将下载好的FluffOS v3.0软件打包成ZIP格式上传到虚拟机home目录下</p></li><li><p><br/></p></li><li><p>9. 虚拟机中图形界面将fluffos包解压到home目录下，切换到命令界面用root权限执行chmod -R 777 home</p></li><li><p><br/></p></li><li><p>10. 编译fluffos开始</p></li><li><p>&nbsp;&nbsp; 10.1 cd 进入解压后的fluffos/src目录 //我们使用源码中local_options.pkuxkx做为配置文件，在图形操作界面进入该目录将该文件后缀去掉</p></li><li><p>&nbsp;&nbsp; 10.2 ./build.FluffOS</p></li><li><p>&nbsp;&nbsp; 10.2 make clean</p></li><li><p>&nbsp;&nbsp; 10.3 make install</p></li><li><p>&nbsp;&nbsp; 10.4 如无意外，在fluffos/bin/已经产生了两个编译好的driver文件</p></li><li><p>&nbsp;&nbsp; 10.5 恭喜你，已经完成了对FluffOS v3.0的编译</p></li><li><p>&nbsp;&nbsp;</p></li><li><p>11. 编译成功后在home/建一个bin目录，把编译好的两个驱动文件放入该目录</p></li><li><p><br/></p></li><li><p>12. 将你的MUDLIB上传到home/并解压到当前目录</p></li><li><p><br/></p></li><li><p>13. 将驱动中的config.cfg移到/home/bin中，与驱动文件放在一起，修改config.cfg中驱动和lib的绝对位置分别指向/home/bin/和/home/你的MUD根目录</p></li><li><p><br/></p></li><li><p>14. 在命令界面中执行</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;14.1 cd home/bin</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;14.2 ./driver config.cfg &amp;</p></li><li><p><br/></p></li><li><p>15. 用你的ZMUD软件，填写上ip addr查到的IP以及你的MUDLIB端口，即可登录，至此，整个过程完成。</p></li><li><p>&nbsp;&nbsp;</p></li><li><p>16. 启动时提示</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;libstdc++.so.6版本过低，搜索该文件在gcc4.8目录下的位置，把gcc4.8编译好的libstdc++.so.6 拷贝到</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;/usr/lib64/下面 覆盖新的文件就行了</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;格式：cp 搜索到的路径/libstdc++.so.6 /usr/lib64</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;如果有相同的文件，系统会提示是否覆盖，选择Y回车</p></li><li><p><br/></p></li><li><p>17. windows 文件放到linux下中文显示乱码解决办法:</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;17.1 cd home/</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;17.2 执行以下指令行：</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;find . -name *.h|xargs dos2unix</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;find . -name *.c|xargs dos2unix</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dos2unix *</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;find . | xargs dos2unix</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;备注：在windows下打包时采用zip格式，在linux下解压出来即可转换成linux格式</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在用ftp上传时，也可选择使用2进制的传输方式</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;</p></li><li><p>18. 提示权限不够时使用以下命令</p></li><li><p>&nbsp;&nbsp;&nbsp;&nbsp;chmod -R 777 目录名</p></li></ol><p><br/></p>]]></description><category>Mud</category><comments>http://www.xiaqiang.com.cn/post/15.html#comment</comments><wfw:commentRss>http://www.xiaqiang.com.cn/feed.asp?cmt=15</wfw:commentRss></item><item><title>fluffos 3.0（alpha8.0）  local_options配置详细选项</title><author>null@null.com (xiaqiang)</author><link>http://www.xiaqiang.com.cn/post/14.html</link><pubDate>Mon, 30 Dec 2013 16:41:30 +0800</pubDate><guid>http://www.xiaqiang.com.cn/post/14.html</guid><description><![CDATA[<p>/*<br/>&nbsp;* options.h: defines for the compile-time configuration of the MudOS driver<br/>&nbsp;*/</p><p>#ifndef _OPTIONS_H_<br/>#define _OPTIONS_H_</p><p>/*<br/>&nbsp;* YOU SHOULD NOT MODIFY THIS FILE DIRECTLY.<br/>&nbsp;*<br/>&nbsp;* Do &#39;cp options.h local_options&#39; and edit that instead.<br/>&nbsp;*<br/>&nbsp;*/</p><p>/****************************************************************************<br/>&nbsp;* EVERY time you change ANYTHING in this file, RECOMPILE from scratch.&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* (type &quot;make clean&quot; then &quot;make&quot; on a UNIX system) Failure to do so may&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* cause the driver to behave oddly.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;****************************************************************************/</p><p>/* NOTES:<br/>&nbsp;* Many of the configurable options are now set via the configuration file<br/>&nbsp;*&nbsp; that is specified as the first argument to the driver.<br/>&nbsp;* See port.h for those #defines related to portability (compatibility) if<br/>&nbsp;*&nbsp; you have problems compiling on your system.<br/>&nbsp;* Removing an efun from func_spec.c usually removes most, if not all,<br/>&nbsp;*&nbsp; of the code associated with it.<br/>&nbsp;* Note that anything defined in this file is also visible to LPC files<br/>&nbsp;* surrounded by __.&nbsp; So #define FOO in this file defines __FOO__ for<br/>&nbsp;* all LPC files.&nbsp; This allows code like:<br/>&nbsp;*<br/>&nbsp;* #ifdef __SENSIBLE_MODIFIERS__<br/>&nbsp;* ...<br/>&nbsp;*/</p><p>/****************************************************************************<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MALLOC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* For performance reasons, LP drivers have a variety of memory allocation&nbsp; *<br/>&nbsp;* packages.&nbsp; If you don&#39;t care, use the default one on your system:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* #define SYSMALLOC, #undef the others.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;****************************************************************************/</p><p>/* You must choose exactly one of these malloc packages:<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; ~~~~<br/>&nbsp;* SYSMALLOC:<br/>&nbsp;*&nbsp;&nbsp; * Built-in system malloc.<br/>&nbsp;*&nbsp;&nbsp; * No statistics.<br/>&nbsp;*&nbsp;&nbsp; * SYSMALLOC incurs no additional CPU or memory overhead.<br/>&nbsp;*<br/>&nbsp;* MALLOC64<br/>&nbsp;*&nbsp;&nbsp; * Wodan&#39;s malloc, uses system malloc for small allocations and spreads<br/>&nbsp;*&nbsp;&nbsp; * large allocations through the 64 bit memory space<br/>&nbsp;*&nbsp;&nbsp; * won&#39;t work on 32 bit systems.<br/>&nbsp;* MALLOC32<br/>&nbsp;*&nbsp;&nbsp; * fixes realloc by always doing a malloc/memcpy/free instead, try this<br/>&nbsp;*&nbsp;&nbsp; * if you use more memory than expected (or MALLOC64 on a 64bit system).<br/>&nbsp;*/<br/>#undef SYSMALLOC<br/>#define MALLOC64<br/>#undef MALLOC32</p><p>/****************************************************************************<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COMPATIBILITY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* The MudOS driver has evolved quite a bit over the years.&nbsp; These defines&nbsp; *<br/>&nbsp;* are mainly to preserve old behavior in case people didn&#39;t want to&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* rewrite the relevant portions of their code.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* In most cases, code which needs these defines should be rewritten when&nbsp;&nbsp; *<br/>&nbsp;* possible.&nbsp; The &#39;Compat status&#39; field is designed to give an idea how&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* likely it is that support for that option will be removed in the near&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* future.&nbsp; Certain options are fairly easy to work around, and double&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* the size of the associated code, as well as the maintenance workload,&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* and can make the code significantly more complex or harder to read, so&nbsp;&nbsp; *<br/>&nbsp;* supporting them indefinitely is impractical.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* WARNING: If you are using software designed to run with the MudOS driver *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; it may assume certain settings of these options.&nbsp; Check the&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instructions for details.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;****************************************************************************/</p><p>/* explode():<br/>&nbsp;*<br/>&nbsp;* The old behavior (#undef both of the below) strips any number of<br/>&nbsp;* delimiters at the start of the string, and one at the end.&nbsp; So<br/>&nbsp;* explode(&quot;..x.y..z..&quot;, &quot;.&quot;) gives ({ &quot;x&quot;, &quot;y&quot;, &quot;&quot;, &quot;z&quot;, &quot;&quot; })<br/>&nbsp;*<br/>&nbsp;* SANE_EXPLODE_STRING strips off at most one leading delimiter, and<br/>&nbsp;* still strips off one at the end, so the example above gives<br/>&nbsp;* ({ &quot;&quot;, &quot;x&quot;, &quot;y&quot;, &quot;&quot;, &quot;z&quot;, &quot;&quot; }).<br/>&nbsp;*<br/>&nbsp;* REVERSIBLE_EXPLODE_STRING overrides SANE_EXPLODE_STRING, and makes<br/>&nbsp;* it so that implode(explode(x, y), y) is always x; i.e. no delimiters<br/>&nbsp;* are ever stripped.&nbsp; So the example above gives<br/>&nbsp;* ({ &quot;&quot;, &quot;&quot;, &quot;x&quot;, &quot;y&quot;, &quot;&quot;, &quot;z&quot;, &quot;&quot;, &quot;&quot; }).<br/>&nbsp;*/<br/>#define SANE_EXPLODE_STRING<br/>#undef REVERSIBLE_EXPLODE_STRING</p><p>/* NO_LIGHT: define this to disable the set_light() and driver maintenance<br/>&nbsp;*&nbsp;&nbsp; of light levels in objects.&nbsp; You can simulate it via LPC if you want...<br/>&nbsp;*<br/>&nbsp;* Compat status: Very dated, easy to simulate, and gross.<br/>&nbsp;*/<br/>#define NO_LIGHT</p><p>/* NO_ADD_ACTION: define this to remove add_action, commands, livings, etc.<br/>&nbsp;* process_input() then becomes the only way to deal with player input.<br/>&nbsp;*<br/>&nbsp;* Compat status: next to impossible to simulate, hard to replace, and<br/>&nbsp;* very, very widely used.<br/>&nbsp;*/<br/>#undef NO_ADD_ACTION</p><p>/* NO_SNOOP: disables the snoop() efun and all related functionality.<br/>&nbsp;*/<br/>#undef NO_SNOOP</p><p>/* NO_ADD_ACTION: define this to remove add_action, commands, livings, etc.<br/>&nbsp;&nbsp; process_input() then becomes the only way to deal with player input. */</p><p>/* NO_ENVIRONMENT: define this to remove the handling of object containment<br/>&nbsp;* relationships by the driver<br/>&nbsp;*<br/>&nbsp;* Compat status: hard to simulate efficiently, and very widely used.<br/>&nbsp;*/<br/>#undef NO_ENVIRONMENT</p><p>/* NO_WIZARDS: for historical reasons, MudOS used to keep track of who<br/>&nbsp;* is and isn&#39;t a wizard.&nbsp; Defining this removes that completely.<br/>&nbsp;* If this is defined, the wizardp() and related efuns don&#39;t exist.<br/>&nbsp;*<br/>&nbsp;* Also note that if it is not defined, then non-wizards are always put<br/>&nbsp;* in restricted mode when ed() is used, regardless of the setting of<br/>&nbsp;* the restrict parameter.<br/>&nbsp;*<br/>&nbsp;* Compat status: easy to simulate and dated.<br/>&nbsp;*/<br/>#undef NO_WIZARDS</p><p>/* OLD_ED: ed() efun backwards compatible with the old version.&nbsp; The new<br/>&nbsp;* version requires/allows a mudlib front end.<br/>&nbsp;*<br/>&nbsp;* Compat status: Easily simulated.<br/>&nbsp;*/<br/>#define OLD_ED</p><p>/* In ed auto-indent,<br/>&nbsp;* 1) does the case line get indented after the switch() ?<br/>&nbsp;* 2) How far do we indent? (this can also be set in the mudlib)<br/>&nbsp;*/<br/>#undef ED_INDENT_CASE<br/>#define ED_INDENT_SPACES 4</p><p>/* SENSIBLE_MODIFIERS:<br/>&nbsp;* Turning this on changes a few things, which may break old code:<br/>&nbsp;*<br/>&nbsp;* (1) &#39;static&#39; is not recognized; either &#39;nosave&#39; or &#39;protected&#39; must<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; be used instead.<br/>&nbsp;* (2) The old meaning of &#39;public&#39; is no longer allowed.&nbsp; Explicit<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; functions must be defined at each level to allow access to<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; privately inherited functions.<br/>&nbsp;* (3) &#39;public&#39; now means the default visibility.&nbsp; Previously there was<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; no keyword that meant this (before you ask, &#39;public&#39; meant something<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; else, and if you don&#39;t know that, you probably don&#39;t have any reason<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; to care about the old meaning).<br/>&nbsp;*/<br/>#undef SENSIBLE_MODIFIERS</p><p>/* SANE_SORTING: Use system provided fastest sorting routine for various<br/>&nbsp;* sorting, including sort_array EFUN.<br/>&nbsp;*<br/>&nbsp;* This replace the old internal version qsort which only sorts to one<br/>&nbsp;* direction repetitively. so following LPC code:<br/>&nbsp;*<br/>&nbsp;*&nbsp;&nbsp;&nbsp; sort_array(({4,3,2,1}), (: -($1&lt;$2) :));<br/>&nbsp;*<br/>&nbsp;* can still return ({1,2,3,4}), even though it only returns -1 and 0.<br/>&nbsp;*<br/>&nbsp;* It is recommended to fix your LPC code to not rely on this behavior.<br/>&nbsp;*<br/>&nbsp;* Your LPC code should return 1, 0, -1 for situation where first argument<br/>&nbsp;* is less than, equal to, or greater than the second argument. This will<br/>&nbsp;* will work with both implementation.<br/>&nbsp;*<br/>&nbsp;* Old code should work fine with this added, easy to inspect by searching<br/>&nbsp;* for sort_array.<br/>&nbsp;*/<br/>#define SANE_SORTING</p><p>/* WARN_TAB: Some versions of the editor built in indent function use<br/>&nbsp;*&nbsp;&nbsp; tabs for indenting. This options turns on a warning message for<br/>&nbsp;*&nbsp;&nbsp; files indented with tabs instead of spaces.<br/>&nbsp;*/<br/>#undef WARN_TAB</p><p>/* WOMBLES: don&#39;t allow spaces between start/end of array/mapping/functional<br/>&nbsp;* token chars so ({1,2,3}) still works, but ( { 1 , 2 , 3 } ) doesn&#39;t<br/>&nbsp;* and ({ 1 , 2 , 3 }) does.*/<br/>#undef WOMBLES</p><p>/* CALL_OTHER_TYPE_CHECK: enable type checking for call_other()<br/>&nbsp;* (-&gt; operator on objects)<br/>&nbsp;*/<br/>#undef CALL_OTHER_TYPE_CHECK</p><p>/* CALL_OTHER_WARN, make it warning instead of errors */<br/>#undef CALL_OTHER_WARN</p><p>/****************************************************************************<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MISCELLANEOUS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* Various options that affect the way the driver behaves.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* WARNING: If you are using software designed to run with the MudOS driver *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; it may assume certain settings of these options.&nbsp; Check the&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instructions for details.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;****************************************************************************/</p><p>/*<br/>&nbsp;* Define this in order to use Fermat@Equilibria&#39;s MD5 based crypt() instead<br/>&nbsp;* of the operating system&#39;s.&nbsp; It has the advantage of giving the same value<br/>&nbsp;* on all architectures, and being stronger than the standard UNIX crypt().<br/>&nbsp;*<br/>&nbsp;* Consider use PACKAGE_CRYPTO instead.<br/>&nbsp;*/<br/>#undef CUSTOM_CRYPT</p><p>/*<br/>&nbsp;* Some minor tweaks that make it a bit easier to run code designed to run<br/>&nbsp;* on LPmud 3.2/3.2.1.&nbsp; Currently has the following effects:<br/>&nbsp;*<br/>&nbsp;* . m_indices() and m_values() are synonyms for keys() and values(),<br/>&nbsp;*&nbsp;&nbsp; respectively<br/>&nbsp;* . map_delete() returns it&#39;s first argument<br/>&nbsp;* . inherit_list() means deep_inherit_list(), not shallow_inherit_list()<br/>&nbsp;* . heart_beat_info() is a synonym for heart_beats()<br/>&nbsp;*/<br/>#undef COMPAT_32</p><p>/* MUDLIB_ERROR_HANDLER: If you define this, the driver doesn&#39;t do any<br/>&nbsp;*&nbsp;&nbsp; handling of runtime errors, other than to turn the heartbeats of<br/>&nbsp;*&nbsp;&nbsp; objects off.&nbsp; Information about the error is passed in a mapping<br/>&nbsp;*&nbsp;&nbsp; to the error_handler() function in the master object.&nbsp; Whatever is<br/>&nbsp;*&nbsp;&nbsp; returned is put in the debug.log.<br/>&nbsp;*<br/>&nbsp;* A good mudlib error handler is one of the best tools for tracking down<br/>&nbsp;* errors.&nbsp; Unfortunately, you need to have one.&nbsp; Check the testsuite or<br/>&nbsp;* other libs for an example.<br/>&nbsp;*/<br/>#define MUDLIB_ERROR_HANDLER</p><p>/* CONFIG_FILE_DIR specifies a directory in which the driver will search for<br/>&nbsp;*&nbsp;&nbsp; config files by default.&nbsp; If you don&#39;t wish to use this define, you may<br/>&nbsp;*&nbsp;&nbsp; always specify a full path to the config file when starting the driver.<br/>&nbsp;*/<br/>#define CONFIG_FILE_DIR &quot;/home/atuin/bin&quot;</p><p>/* DEFAULT_PRAGMAS:&nbsp; This should be a sum of pragmas you want to always<br/>&nbsp;* be on, i.e.<br/>&nbsp;*<br/>&nbsp;* #define DEFAULT_PRAGMAS PRAGMA_STRICT_TYPES + PRAGMA_SAVE_TYPES<br/>&nbsp;*<br/>&nbsp;* will make every LPC file behave as if it had the lines:<br/>&nbsp;* #pragma strict_types<br/>&nbsp;* #pragma save_types<br/>&nbsp;*<br/>&nbsp;* for no default pragmas:<br/>&nbsp;* #define DEFAULT_PRAGMAS 0<br/>&nbsp;*<br/>&nbsp;* If you don&#39;t know what these are, 0 is a good choice.<br/>&nbsp;*<br/>&nbsp;* Supported pragmas:<br/>&nbsp;* PRAGMA_STRICT_TYPES: enforces strict type checking<br/>&nbsp;* PRAGMA_WARNINGS:&nbsp;&nbsp;&nbsp;&nbsp; issues warnings about various dangerous things in<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; your code<br/>&nbsp;* PRAGMA_SAVE_TYPES:&nbsp;&nbsp; save the types of function arguments for checking<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; calls to functions in this object by objects that<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inherit it.<br/>&nbsp;* PRAGMA_OPTIMIZE:&nbsp;&nbsp;&nbsp;&nbsp; make a second pass over the generated code to<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; optimize it further.<br/>&nbsp;* PRAGMA_ERROR_CONTEXT:include some text telling where on the line a<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; compilation error occured.<br/>&nbsp;*/<br/>#define DEFAULT_PRAGMAS PRAGMA_SAVE_TYPES + PRAGMA_ERROR_CONTEXT</p><p>/* NO_RESETS: completely disable the periodic calling of reset() */<br/>#undef NO_RESETS</p><p>/* LAZY_RESETS: if this is defined, an object will only have reset()<br/>&nbsp;*&nbsp;&nbsp; called in it when it is touched via call_other() or move_object()<br/>&nbsp;*&nbsp;&nbsp; (assuming enough time has passed since the last reset).&nbsp; If LAZY_RESETS<br/>&nbsp;*&nbsp;&nbsp; is #undef&#39;d, then reset() will be called as always (which guaranteed that<br/>&nbsp;*&nbsp;&nbsp; reset would always be called at least once).&nbsp; The advantage of lazy<br/>&nbsp;*&nbsp;&nbsp; resets is that reset doesn&#39;t get called in an object that is touched<br/>&nbsp;*&nbsp;&nbsp; once and never again (which can save memory since some objects won&#39;t get<br/>&nbsp;*&nbsp;&nbsp; reloaded that otherwise would).<br/>&nbsp;*/<br/>#undef LAZY_RESETS</p><p><br/>/* RANDOMIZED_RESETS: if this is defined, the reset() will be called in randomized<br/>&nbsp;*&nbsp;&nbsp; time interval. The interval vary from TIME_TO_RESET/2 to TIME_TO_RESET-1 .<br/>&nbsp;*&nbsp;&nbsp; if this is undefined, the reset() will be called among all objects at the same time,<br/>&nbsp;*&nbsp;&nbsp; with the interval as TIME_TO_RESET<br/>*/<br/>#undef RANDOMIZED_RESETS</p><p>/* SAVE_EXTENSION: defines the file extension used by save_object().<br/>&nbsp;*&nbsp;&nbsp; and restore_object().&nbsp; Some sysadmins run scripts that periodically<br/>&nbsp;*&nbsp;&nbsp; scan for and remove files ending in .o (but many mudlibs are already<br/>&nbsp;*&nbsp;&nbsp; set up to use .o thus we leave .o as the default).<br/>&nbsp;*/<br/>#define SAVE_EXTENSION &quot;.o&quot;</p><p>/* NO_ANSI: define if you wish to disallow users from typing in commands that<br/>&nbsp;*&nbsp;&nbsp; contain ANSI escape sequences.&nbsp; Defining NO_ANSI causes all escapes<br/>&nbsp;*&nbsp;&nbsp; (ASCII 27) to be replaced with a space &#39; &#39; before the string is passed<br/>&nbsp;*&nbsp;&nbsp; to the action routines added with add_action.<br/>&nbsp;*<br/>&nbsp;* STRIP_BEFORE_PROCESS_INPUT allows the location where the stripping is<br/>&nbsp;* done to be controlled.&nbsp; If it is defined, then process_input() doesn&#39;t<br/>&nbsp;* see ANSI characters either; if it is undefined ESC chars can be processed<br/>&nbsp;* by process_input(), but are stripped before add_actions are called.<br/>&nbsp;* Note that if NO_ADD_ACTION is defined, then #define NO_ANSI without<br/>&nbsp;* #define STRIP_BEFORE_PROCESS_INPUT is the same as #undef NO_ANSI.<br/>&nbsp;*<br/>&nbsp;* If you anticipate problems with users intentionally typing in ANSI codes<br/>&nbsp;* to make your terminal flash, etc define this.<br/>&nbsp;*/<br/>#define NO_ANSI<br/>#define STRIP_BEFORE_PROCESS_INPUT</p><p>/* OPCPROF: define this if you wish to enable OPC profiling. Allows a dump<br/>&nbsp;*&nbsp;&nbsp; of the # of times each efun is invoked (via the opcprof() efun).<br/>&nbsp;*/<br/>#undef OPCPROF</p><p>/* OPCPROF_2D: define this if you wish to enable 2-D OPC profiling. Allows a<br/>&nbsp;*&nbsp;&nbsp; dump of the # of times each *pair* of eoperators is invoked.<br/>&nbsp;*<br/>&nbsp;* You can&#39;t use this and OPCPROF at the same time.<br/>&nbsp;*/<br/>#undef OPCPROF_2D</p><p>/* THIS_PLAYER_IN_CALL_OUT: define this if you wish this_player() to be<br/>&nbsp;*&nbsp;&nbsp; usable from within call_out() callbacks.<br/>&nbsp;*/<br/>#define THIS_PLAYER_IN_CALL_OUT</p><p>/* CALLOUT_LOOP_PROTECTION: If this is defined, all new zero-delay call_outs<br/>&nbsp;* added while already processing call_outs will run under a single evaluation<br/>&nbsp;* cost allotment.&nbsp; In the event of an infinite loop, the eval timer will<br/>&nbsp;* expire and a &quot;Maximum evaluation cost&quot; error will be thrown.<br/>&nbsp;*<br/>&nbsp;* If this option is undefined, all call_outs (including zero-delay ones added<br/>&nbsp;* by another call_out) will be given a full evaluation time budget.&nbsp; Unless<br/>&nbsp;* the mudlib takes steps to protect against loops by overriding call_out()<br/>&nbsp;* with a sefun, an infinite loop will hang the driver, requiring it to be<br/>&nbsp;* killed and restarted.<br/>&nbsp;*<br/>&nbsp;* Old code should work fine with this added.<br/>&nbsp;*/<br/>#define CALLOUT_LOOP_PROTECTION</p><p>/* FLUSH_OUTPUT_IMMEDIATELY: Causes output to be written to sockets<br/>&nbsp;* immediately after being generated.&nbsp; Useful for debugging.<br/>&nbsp;*/<br/>#undef FLUSH_OUTPUT_IMMEDIATELY</p><p>/* PRIVS: define this if you want object privileges.&nbsp; Your mudlib must<br/>&nbsp;*&nbsp;&nbsp; explicitly make use of this functionality to be useful.&nbsp; Defining this<br/>&nbsp;*&nbsp;&nbsp; this will increase the size of the object structure by 4 bytes (8 bytes<br/>&nbsp;*&nbsp;&nbsp; on the DEC Alpha) and will add a new master apply during object creation<br/>&nbsp;*&nbsp;&nbsp; to &quot;privs_file&quot;.&nbsp; In general, privileges can be used to increase the<br/>&nbsp;*&nbsp;&nbsp; granularity of security beyond the current root uid mechanism.<br/>&nbsp;*<br/>&nbsp;* [NOTE: for those who&#39;d rather do such things at the mudlib level, look at<br/>&nbsp;*&nbsp; the inherits() efun and the &#39;valid_object&#39; apply to master.]<br/>&nbsp;*/<br/>#undef PRIVS</p><p>/* INTERACTIVE_CATCH_TELL: define this if you want catch_tell called on<br/>&nbsp;*&nbsp;&nbsp; interactives as well as NPCs.&nbsp; If this is defined, user.c will need a<br/>&nbsp;*&nbsp;&nbsp; catch_tell(msg) method that calls receive(msg);<br/>*/<br/>#undef INTERACTIVE_CATCH_TELL</p><p>/* RECEIVE_ED: define this if you want normal ed output to go to a<br/>&nbsp;&nbsp;&nbsp;&nbsp; receive_ed() apply in the player ob.&nbsp; Some errors still go directly<br/>&nbsp;&nbsp;&nbsp;&nbsp; to output.&nbsp; Useful for post-processing (perhaps colorizing?) ed<br/>&nbsp;&nbsp;&nbsp;&nbsp; output. Prototype:&nbsp; mixed receive_ed(string txt, string fname);<br/>&nbsp;&nbsp;&nbsp;&nbsp; If fname, return a string that ed will output, 0 to let ed handle<br/>&nbsp;&nbsp;&nbsp;&nbsp; the output in the default way, or 1 to handle the output yourself.<br/>&nbsp;&nbsp;&nbsp;&nbsp; If fname == 0, output is help text and you may return any of the above<br/>&nbsp;&nbsp;&nbsp;&nbsp; or an array of strings that will be more&#39;ed.<br/>*/<br/>#undef RECEIVE_ED</p><p>/* RESTRICTED_ED: define this if you want restricted ed mode enabled.<br/>&nbsp;*/<br/>#define RESTRICTED_ED</p><p>/* NO_SHADOWS: define this if you want to disable shadows in your driver.<br/>&nbsp;*/<br/>#undef NO_SHADOWS</p><p>/* SNOOP_SHADOWED: define this if you want snoop to report what is<br/>&nbsp;*&nbsp;&nbsp; sent to the player even in the event that the player&#39;s catch_tell() is<br/>&nbsp;*&nbsp;&nbsp; shadowed and the player may not be seeing what is being sent.&nbsp; Messages<br/>&nbsp;*&nbsp;&nbsp; of this sort will be prefixed with $$.<br/>&nbsp;*/<br/>#undef SNOOP_SHADOWED</p><p>/* RECEIVE_SNOOP: define this if you want snoop text to be sent to<br/>&nbsp;*&nbsp;&nbsp; the receive_snoop() function in the snooper object (instead of being<br/>&nbsp;*&nbsp;&nbsp; sent directly via add_message()).&nbsp; This is useful if you want to<br/>&nbsp;*&nbsp;&nbsp; build a smart client that does something different with snoop messages.<br/>&nbsp;*/<br/>#define RECEIVE_SNOOP</p><p>/* PROFILE_FUNCTIONS: define this to be able to measure the CPU time used by<br/>&nbsp;*&nbsp;&nbsp; all of the user-defined functions in each LPC object.&nbsp; Note: defining<br/>&nbsp;*&nbsp;&nbsp; this adds three long ints (12 bytes on 32-bit machines) to the function<br/>&nbsp;*&nbsp;&nbsp; header structs.&nbsp; Also note that the resolution of the getrusage() timer<br/>&nbsp;*&nbsp;&nbsp; may not be high enough on some machines to give non-zero execution<br/>&nbsp;*&nbsp;&nbsp; times to very small (fast) functions.&nbsp; In particular if the clock<br/>&nbsp;*&nbsp;&nbsp; resolution is 1/60 of a second, then any time less than approxmately 15k<br/>&nbsp;*&nbsp;&nbsp; microseconds will resolve to zero (0).<br/>&nbsp;*/<br/>#undef PROFILE_FUNCTIONS</p><p>/****************************************************************************<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PACKAGES&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* Defining some/all of the following add certain efuns, and sometimes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* add/remove code from the driver.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* if PACKAGE_XYZZY is defined here, then the code in packages/xyzzy.c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* and the efuns in packages/xyzzy_spec.c will be added to the driver.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;****************************************************************************/</p><p>/* various miscellaneous efuns */<br/>#define PACKAGE_CONTRIB</p><p>/* efuns that are only of use to those that know something about driver<br/>&nbsp;&nbsp; internals */<br/>#define PACKAGE_DEVELOP</p><p>/* PACKAGE_MATH: determines whether or not the math efuns (for floats) are<br/>&nbsp;&nbsp; included.<br/>&nbsp;*/<br/>#define PACKAGE_MATH</p><p>/* PACKAGE_MATRIX: determines whether or not the 3d graphics efuns (for floats)<br/>&nbsp;*&nbsp;&nbsp; are included - see packages/matrix.spec for a list.<br/>&nbsp;*/<br/>#undef PACKAGE_MATRIX</p><p>/* PACKAGE_MUDLIB_STATS: define this to enable domain and author stats<br/>&nbsp;*&nbsp;&nbsp; maintenance by the driver.&nbsp; These mudlib stats are more domain<br/>&nbsp;*&nbsp;&nbsp; based than user based, and replaces the traditional wiz_list stats.<br/>&nbsp;*/<br/>#define PACKAGE_MUDLIB_STATS</p><p>/* PACKAGE_SOCKETS: define this to enable the socket efunctions.&nbsp; This<br/>&nbsp;*&nbsp;&nbsp; causes HAS_SOCKETS to be defined for all LPC objects.<br/>&nbsp;*/<br/>#define PACKAGE_SOCKETS</p><p>/* PACKAGE_PARSER: Natural language parsing efuns for interactive fiction<br/>&nbsp;*&nbsp;&nbsp; type applications<br/>&nbsp;*/<br/>#undef PACKAGE_PARSER</p><p>/* PACKAGE_EXTERNAL: Allows the driver to exec() commands specified in the<br/>&nbsp;* config file.<br/>&nbsp;*/<br/>#define PACKAGE_EXTERNAL</p><p>/* NUM_EXTERNAL_CMDS: the number of external commands supported */<br/>#ifdef PACKAGE_EXTERNAL<br/>#define NUM_EXTERNAL_CMDS 100<br/>#endif</p><p>/* PACKAGE_DB: efuns for external database access using msql */<br/>#undef PACKAGE_DB</p><p>/* If PACKAGE_DB is defined above, you must pick ONE of the following supported<br/>&nbsp;* databases<br/>&nbsp;*/<br/>#ifdef PACKAGE_DB<br/>#undef USE_MSQL<br/>#define USE_MYSQL 1<br/>#undef USE_POSTGRES<br/>#undef USE_SQLITE3<br/>#endif</p><p>/*PACKAGE_ASYNC: adds some efuns for asyncronous IO */<br/>#define PACKAGE_ASYNC</p><p>/*PACKAGE_SHA1: adds a function to calculate the sha1 hash of a string sha1(string).&nbsp; Use PACKAGE_CRYPTO instead if possible. */<br/>#define PACKAGE_SHA1</p><p>/*PACKAGE_CRYPTO: adds a function that does multiple hash types hash(hash, string), needs openssl lib and includes and -lssl in system_libs*/<br/>#undef PACKAGE_CRYPTO</p><p>/*<br/>&nbsp; PACKAGE_TRIM: efuns for remove leading / trailing whitepsaces (or chars in provided charset)<br/>&nbsp; Functions:<br/>&nbsp;&nbsp;&nbsp; - trim: Remove leading and trailing whitespaces (or in provided charset).<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Example:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - &quot;&nbsp;&nbsp;&nbsp; my test&nbsp;&nbsp; &quot; : &quot;my test&quot;<br/>&nbsp;&nbsp;&nbsp; - ltrim: Remove leading whitespaces (and others).<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Example:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - &quot;&nbsp;&nbsp;&nbsp; my test&nbsp;&nbsp; &quot; : &quot;my test&nbsp;&nbsp; &quot;<br/>&nbsp;&nbsp;&nbsp; - rtrim: Remove trailing whitespaces (and others).<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Example:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - &quot;&nbsp;&nbsp;&nbsp; my test&nbsp;&nbsp; &quot; : &quot;&nbsp;&nbsp;&nbsp; my test&quot;</p><p>&nbsp; Characters that remove by default: isspace() == 1, which is:<br/>&nbsp;&nbsp;&nbsp; &#39; &#39; (0x20)&nbsp; space (SPC)<br/>&nbsp;&nbsp;&nbsp; &#39;\t&#39;&nbsp; (0x09)&nbsp; horizontal tab (TAB)<br/>&nbsp;&nbsp;&nbsp; &#39;\n&#39;&nbsp; (0x0a)&nbsp; newline (LF)<br/>&nbsp;&nbsp;&nbsp; &#39;\v&#39;&nbsp; (0x0b)&nbsp; vertical tab (VT)<br/>&nbsp;&nbsp;&nbsp; &#39;\f&#39;&nbsp; (0x0c)&nbsp; feed (FF)<br/>&nbsp;&nbsp;&nbsp; &#39;\r&#39;&nbsp; (0x0d)&nbsp; carriage return (CR)<br/>&nbsp;*/<br/>#define PACKAGE_TRIM</p><p>/*PACKAGE DWLIB: some discworld mudlib simuls coded in C (well just one right<br/>&nbsp; now) */</p><p>#undef PACKAGE_DWLIB</p><p>/****************************************************************************<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UID PACKAGE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* UIDS are the basis for some mudlib security systems.&nbsp; Basically, they&#39;re *<br/>&nbsp;* preserved for backwards compatibility, as several ways of breaking&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* almost any system which relies on them are known.&nbsp; (No, it&#39;s not a flaw&nbsp; *<br/>&nbsp;* of uids; only that b/c of the ease with which LPC objects can call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* each other, it&#39;s far too easy to leave holes)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* If you don&#39;t care about security, the first option is probably what you&nbsp; *<br/>&nbsp;* want.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;****************************************************************************/</p><p>/*<br/>&nbsp;* PACKAGE_UIDS: define this if you want a driver that does use uids.<br/>&nbsp;*<br/>&nbsp;*/<br/>#define PACKAGE_UIDS</p><p>#ifdef PACKAGE_UIDS<br/>/* AUTO_SETEUID: when an object is created it&#39;s euid is automatically set to<br/>&nbsp;*&nbsp;&nbsp; the equivalent of seteuid(getuid(this_object())).&nbsp; undef AUTO_SETEUID<br/>&nbsp;*&nbsp;&nbsp; if you would rather have the euid of the created object be set to 0.<br/>&nbsp;*/<br/>#define AUTO_SETEUID</p><p>/* AUTO_TRUST_BACKBONE: define this if you want objects with the backbone<br/>&nbsp;*&nbsp;&nbsp; uid to automatically be trusted and to have their euid set to the uid of<br/>&nbsp;*&nbsp;&nbsp; the object that forced the object&#39;s creation.<br/>&nbsp;*/<br/>#undef AUTO_TRUST_BACKBONE<br/>#endif</p><p>/*************************************************************************<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FOR EXPERIENCED USERS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----------------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br/>&nbsp;* Most of these options will probably be of no interest to many users.&nbsp; *<br/>&nbsp;*************************************************************************/</p><p>/* USE_32BIT_ADDRESSES: Use 32 bits for addresses of function, instead of<br/>&nbsp;* the usual 16 bits.&nbsp; This increases the maximum program size from 64k<br/>&nbsp;* of LPC bytecode (NOT source) to 4 GB.&nbsp; Branches are still 16 bits,<br/>&nbsp;* imposing a 64k limit on catch(), if(), switch(), loops, and most other<br/>&nbsp;* control structures.&nbsp; It would take an extremely large function to hit<br/>&nbsp;* those limits, though.<br/>&nbsp;*<br/>&nbsp;* Overhead: 2 bytes/function with LPC-&gt;C off.&nbsp; Having LPC-&gt;C on forces<br/>&nbsp;* this option, since it needs 4 bytes to store the function pointers<br/>&nbsp;* anyway, and this setting is ignored.<br/>&nbsp;*/<br/>#undef USE_32BIT_ADDRESSES</p><p>/* HEARTBEAT_INTERVAL: define heartbeat interval in seconds.<br/>&nbsp;*/<br/>#define HEARTBEAT_INTERVAL 2</p><p>/* LARGEST_PRINTABLE_STRING: defines the size of the vsprintf() buffer in<br/>&nbsp;*&nbsp;&nbsp; comm.c&#39;s add_message(). Instead of blindly making this value larger,<br/>&nbsp;*&nbsp;&nbsp; your mudlib should be coded to not send huge strings to users.<br/>&nbsp;*/<br/>#define LARGEST_PRINTABLE_STRING 8192</p><p>/* MESSAGE_BUFFER_SIZE: determines the size of the buffer for output that<br/>&nbsp;*&nbsp;&nbsp; is sent to users.<br/>&nbsp;*/<br/>#define MESSAGE_BUFFER_SIZE 4096</p><p>/* TRACE: define this to enable the trace() and traceprefix() efuns.<br/>&nbsp;*&nbsp;&nbsp; (keeping this undefined will cause the driver to run faster).<br/>&nbsp;*/<br/>#define TRACE</p><p>/* TRACE_CODE: define this to enable code tracing (the driver will print<br/>&nbsp;*&nbsp;&nbsp; out the previous lines of code to an error) eval_instruction() runs about<br/>&nbsp;*&nbsp;&nbsp; twice as fast when this is not defined (for the most common eoperators).<br/>&nbsp;*/<br/>#undef TRACE_CODE</p><p>/* GET_CHAR_IS_BUFFERED: Normally get_char() is unbuffered.&nbsp; That is, once<br/>&nbsp;* a character is received for get_char(), anything else is in the input<br/>&nbsp;* stream is immediately thrown away.&nbsp; This can be very undesirable, especially<br/>&nbsp;* if you&#39;re calling get_char() again from the handler from the previous call.<br/>&nbsp;* Define this if you want get_char() to be buffered.&nbsp; In this case, the buffer<br/>&nbsp;* will only get flushed if get_char() is not called from the first get_char()&#39;s<br/>&nbsp;* LPC callback handler.<br/>&nbsp;*/<br/>#undef GET_CHAR_IS_BUFFERED</p><p>/* PACKAGE_COMPRESS: Enable MCCP support and compressed save files<br/>&nbsp;&nbsp; SAVE_GZ_EXTENSION: save extension for compressed files<br/>&nbsp;*/<br/>#define HAVE_ZLIB<br/>#define PACKAGE_COMPRESS<br/>#define SAVE_GZ_EXTENSION &quot;.o.gz&quot;</p><p>/* USE_ICONV: Use iconv to translate input and output from/to the users char<br/>&nbsp;* encoding<br/>&nbsp;*/<br/>#undef USE_ICONV</p><p>/* HAS_CONSOLE: If defined, the driver can take the argument -C<br/>&nbsp;*&nbsp;&nbsp; which will give the driver an interactive console (you can type<br/>&nbsp;*&nbsp;&nbsp; commands at the terminal.)&nbsp; Backgrounding the driver will turn off<br/>&nbsp;*&nbsp;&nbsp; the console, but sending signal SIGTTIN (kill -21) to the driver can<br/>&nbsp;*&nbsp;&nbsp; turn it back on.&nbsp; Typing &#39;help&#39; will display commands available.<br/>&nbsp;*&nbsp;&nbsp; The intent is to allow the inspection of things that are difficult<br/>&nbsp;*&nbsp;&nbsp; to inspect from inside the mud.<br/>&nbsp;*/<br/>#define HAS_CONSOLE</p><p>/* IPV6: Use IP version 6 instead of 4, for most people the only difference<br/>&nbsp;* will be that numerical IP addresses get ::ffff: added in front.*/<br/>#undef IPV6</p><p>/* static user space dtrace probes, try them if you have dtrace! */<br/>#undef DTRACE</p><p>/* use POSIX timers for eval_cost.<br/>&nbsp;*<br/>&nbsp;* Old code should works fine with this added.<br/>&nbsp;*/<br/>#define POSIX_TIMERS</p><p>/*<br/>&nbsp; REVERSE_DEFER:</p><p>&nbsp; If not defined executes defer functions in LIFO mode.</p><p>&nbsp; If defined executes defer functions in FIFO mode.<br/>*/<br/>#undef REVERSE_DEFER</p><p><br/>#endif /* _OPTIONS_H */<br/></p><p><br/></p>]]></description><category>Mud</category><comments>http://www.xiaqiang.com.cn/post/14.html#comment</comments><wfw:commentRss>http://www.xiaqiang.com.cn/feed.asp?cmt=14</wfw:commentRss></item><item><title>options.h配置详细选项</title><author>null@null.com (xiaqiang)</author><link>http://www.xiaqiang.com.cn/post/13.html</link><pubDate>Mon, 26 Aug 2013 14:49:22 +0800</pubDate><guid>http://www.xiaqiang.com.cn/post/13.html</guid><description><![CDATA[<p>&nbsp;</p><p>/* options.h配置详细选项<br/>—————————————————————————-<br/>将 MudOS 下载解压以后可以在相应目录的根目录中找到 options.h 这个文件。如果修<br/>&nbsp;改了这个文件，那么每次都需要重新编译 MudOS 才能生效。重新编译之前，请执行 ma<br/>&nbsp;ke clean 一下。<br/>&nbsp;下面的 options.h 来自 MudOSv22.2b10，MudOS作者推荐在修改options.h 之前，先将<br/>&nbsp;它备份成 local_options。新的特性将会自动对比local_options并且在编译的时候告知<br/>&nbsp;。文中的选项定义并非最原始的定义。此文只是为了说明各个选项的大致含义。<br/>options.h: defines for the compile-time configuration of the MudOS driver<br/>&nbsp;*/</p><p>#ifndef _OPTIONS_H_<br/>&nbsp;#define _OPTIONS_H_</p><p>/****************************************************************************<br/>如果你对自己的系统不熟悉，请使用缺省的定义 SYSMALLOC，同时将其它的undef掉。<br/>&nbsp;你必须选择下面的其中一种定义，并且将其它的定义undef掉。<br/>SYSMALLOC: 缺省选项，没有额外的系统开支，没有统计能力。<br/>SMALLOC:速度比较快，但是开销相对大一些。<br/>BSDMALLOC:速度更快，开销比较大。<br/>****************************************************************************/</p><p>#define SYSMALLOC<br/>&nbsp;#undef SMALLOC<br/>&nbsp;#undef BSDMALLOC</p><p>/****************************************************************************<br/>&nbsp;WRAPPEDMALLOC:这个附加定义可以换来有限的统计能力，并且不会增加太多的系统开销。<br/>DEBUGMALLOC:系统花费比较折中<br/>****************************************************************************/<br/>&nbsp;#undef WRAPPEDMALLOC<br/>&nbsp;#undef DEBUGMALLOC</p><p>/****************************************************************************<br/>如果没有定义SMALLOC，请不要使用下面这个定义。<br/>****************************************************************************/<br/>&nbsp;#undef SBRK_OK</p><p>/****************************************************************************<br/>如果没有定义 BSDMALLOC or SMALLOC ，请不要使用下面这个定义<br/>****************************************************************************/<br/>&nbsp;#undef DO_MSTATS</p><p>/****************************************************************************<br/>&nbsp;DEBUGMALLOC定义的附加定义，用来强化DEBUGMALLOC，但是需要更多的开销。<br/>set_malloc_mask(int) and debugmalloc(string,int)等efuns将可以被使用。<br/>****************************************************************************/<br/>&nbsp;#undef DEBUGMALLOC_EXTENSIONS</p><p>/****************************************************************************<br/>同上，是用来调试的良好定义，check_memory() efun将可以被使用。<br/>****************************************************************************/<br/>&nbsp;#undef CHECK_MEMORY</p><p>/****************************************************************************<br/>兼容性定义选项：<br/>&nbsp;由于MudOS发展了很多年，所以历代MudOS为了保证原有的Lib可以不修改就被移植到新的<br/>OS上面，增加了这些兼容性选项。如果你是根据OS撰写Lib的人，可以定义一些优化的选<br/>&nbsp;项来设计自己的Lib，而不必考虑重写的问题。<br/>&nbsp;以前的MudOS使用status这样子的定义词，这是很老的定义了，对于新的Lib设计而言，<br/>&nbsp;这个定义毫无用处。<br/>****************************************************************************/<br/>&nbsp;#undef HAS_STATUS_TYPE</p><p>/****************************************************************************<br/>&nbsp;explode()选项，这个根据个人的习惯来定义吧<br/>&nbsp;如果不定义下面两个选项， explode(“..x.y..z..”, “.”) 的结果是 ({ “x”, “y”, “”<br/>, “z”, “” })<br/>如果定义SANE_EXPLODE_STRING 选项，其结果将是({ “”, “x”, “y”, “”, “z”, “” })<br/>如果定义 REVERSIBLE_EXPLODE_STRING 选项，其结果将是 ({ “”, “”, “x”, “y”, “”,<br/>“z”, “”, “” })<br/>&nbsp;****************************************************************************/<br/>&nbsp;#define SANE_EXPLODE_STRING<br/>&nbsp;#undef REVERSIBLE_EXPLODE_STRING</p><p>/****************************************************************************<br/>这个选项用来确定call_other的行为，但是这个选项对于系统毫无好处可言。<br/>****************************************************************************/<br/>&nbsp;#undef CAST_CALL_OTHERS</p><p>/****************************************************************************<br/>如果定义了下面这个选项，那么任何传往非交互式物件（比如npc）的信息前面都会被加<br/>&nbsp;上’]&#39;符号，这个也不是非常需要，而且很容易被模拟出来。<br/>****************************************************************************/<br/>&nbsp;#undef NONINTERACTIVE_STDERR_WRITE</p><p>/****************************************************************************<br/>如果定义下面这个选项，你将不能使用set_light()这样的efuns函数，不过没有关系，<br/>&nbsp;这个函数是在太落伍了，这个功能非常容易被模拟出来。<br/>****************************************************************************/<br/>&nbsp;#define NO_LIGHT</p><p>/****************************************************************************<br/>嗯，下面这个选项，是非常重要的选项，如果你定义了，那么意味着你将不能使用add_<br/>&nbsp;action, commands, livings等等这些相关的efuns，而不得不使用 process_input() 这<br/>&nbsp;样的函数来定义物件所有的动作。这将是非常难堪的工作。所以保持add_action还是非<br/>&nbsp;常有用的。<br/>****************************************************************************/<br/>&nbsp;#undef NO_ADD_ACTION</p><p>/****************************************************************************<br/>定义下面这个选项，将不能使用和snoop相关的函数，如果你认为没有snoop也没有关系<br/>&nbsp;，可以定义这个选项来保护一些隐私。<br/>****************************************************************************/<br/>&nbsp;#undef NO_SNOOP</p><p>/****************************************************************************<br/>这个选项和add_action一样要命，除非你立志只做一个聊天室，那么可以定义这个选项<br/>&nbsp;，否则，你的工作将会非常的麻烦。<br/>****************************************************************************/<br/>&nbsp;#undef NO_ENVIRONMENT</p><p>/****************************************************************************<br/>由于历史原因，定义wizard来管理Mud的运作，但是现在好像不是非常重要了。<br/>&nbsp;如果定义了, wizardp() 和 related efuns 将不存在<br/>&nbsp;如果没有定义，在使用ed()时也受限制，设置的限制参数无效<br/>&nbsp;而且这个定义非常容易模拟出来。<br/>****************************************************************************/<br/>&nbsp;#undef NO_WIZARDS</p><p>/****************************************************************************<br/>下面的选项只是为了保持兼容性问题，对于大多数的LPmud而言，这个选项毫无用处。尤<br/>&nbsp;其是一个新的Lib撰写。<br/>****************************************************************************/<br/>&nbsp;#undef OLD_TYPE_BEHAVIOR</p><p>/****************************************************************************<br/>定义下面这个选项，将意味着对于一个string或者buffers而言可以使用负数的index。<br/>&nbsp;对于一个新Lib撰写，这个属性不是非常重要。<br/>****************************************************************************/<br/>&nbsp;#undef OLD_RANGE_BEHAVIOR</p><p>/****************************************************************************<br/>这个定义选项主要是为了保持向后兼容，对于新的Lib而言，没什么用处。重新习惯一个<br/>&nbsp;方式，并不是非常困难的，而且，ed()对于大多数习惯使用工具撰写的人们而言，意义<br/>&nbsp;不大。<br/>****************************************************************************/<br/>&nbsp;#define OLD_ED</p><p>/****************************************************************************<br/>下面这个选项比较重要，对于新的Lib撰写或者以前没有接触过LPC的人来说，这个定义<br/>&nbsp;可以按照喜好来定。<br/>(1) ‘static’ 将不再使用，而是用 ‘nosave’ 或者 ‘protected’ 代替了它。.<br/>&nbsp;(2) ‘public’ 含义发生了变化，外部函数必须在任何一级的继承中被声明。现在publi<br/>&nbsp;c意味着是明显可见的。<br/>****************************************************************************/<br/>&nbsp;#define SENSIBLE_MODIFIERS</p><p>/****************************************************************************<br/>下面的选项定义会改变MudOS的一些行为。这些对于Lib撰写，是比较重要的。<br/>&nbsp;定义下面这个选项，将使用MD5加密法代替系统缺省的crypt()加密法。<br/>****************************************************************************/<br/>&nbsp;#undef CUSTOM_CRYPT</p><p>/****************************************************************************<br/>下面这个选项只是为了一些兼容性问题。定义以后，某些efuns含义会有所变化，但是没<br/>&nbsp;有实质的区别。<br/>****************************************************************************/<br/>&nbsp;#undef COMPAT_32</p><p>/****************************************************************************<br/>允许统计的时候包含字符串分配，不定义可以是字符串处理更快，但字符串统计将被忽略。<br/>****************************************************************************/<br/>&nbsp;#define STRING_STATS</p><p>/****************************************************************************<br/>同上，数组统计。<br/>****************************************************************************/<br/>&nbsp;#define ARRAY_STATS</p><p>/****************************************************************************<br/>这是比较有用的选项，用来生成log文件。<br/>****************************************************************************/<br/>&nbsp;#define LOG_CATCHES</p><p>/****************************************************************************<br/>这个类似上面得选项，可以生成有用的调试文档。<br/>****************************************************************************/<br/>&nbsp;#define ARGUMENTS_IN_TRACEBACK</p><p>/****************************************************************************<br/>同上，对于新Lib撰写非常有用。<br/>****************************************************************************/<br/>&nbsp;#define LOCALS_IN_TRACEBACK</p><p>/****************************************************************************<br/>通过error_handler()来处理错误，非常有用的选项。<br/>****************************************************************************/<br/>&nbsp;#define MUDLIB_ERROR_HANDLER</p><p>/****************************************************************************<br/>下面得选项，可以详细定义，当然也可以通过配置config.cfg这样的文件来设置。<br/>****************************************************************************/<br/>&nbsp;#ifndef LATTICE<br/>&nbsp;#define CONFIG_FILE_DIR “/u/tim/COMP/bin”<br/>#else<br/>&nbsp;#define CONFIG_FILE_DIR “etc:”<br/>#endif</p><p>/****************************************************************************<br/>下面的选项将会对整个Lib撰写起到作用。对于新的Lib撰写，建议选择比较严格的方式<br/>&nbsp;。而如果想保持兼容，建议选择常规的设定。<br/>&nbsp;这些设定　其实等同于使用 #pragma　来定义。<br/>&nbsp;如果你不太明白，使用 #define DEFAULT_PRAGMAS 0　是一个比较好的选择。<br/>PRAGMA_STRICT_TYPES: 强制执行严格的书写规则，这个估计是以前议论最多的问题，<br/>&nbsp;事实上，对于新Lib，这几乎不是问题。<br/>PRAGMA_WARNINGS: 对不合法代码进行警告。非常有用。<br/>PRAGMA_SAVE_TYPES: 呼叫以后保存函数情况<br/>PRAGMA_SAVE_BINARY: 二进制代码保存，可以降低系统负担。<br/>PRAGMA_OPTIMIZE: 代码优化<br/>PRAGMA_ERROR_CONTEXT:错误报告<br/>****************************************************************************/<br/>&nbsp;#define DEFAULT_PRAGMAS PRAGMA_SAVE_BINARY + PRAGMA_WARNINGS + PRAGMA_ERROR_CONTEXT</p><p>/****************************************************************************<br/>对于没有使用的变量声明或者缺少的参数进行报告<br/>****************************************************************************/<br/>&nbsp;#define SUPPRESS_ARGUMENT_WARNINGS</p><p>/****************************************************************************<br/>这是重要的设定，为了保证系统拥有reset()，请不要定义这个选项。<br/>&nbsp;除非不想系统拥有reset()。<br/>****************************************************************************/<br/>&nbsp;#undef NO_RESETS</p><p>/****************************************************************************<br/>看名字就知道，如果定义了，reset()将变得比较懒惰，你不碰它，它不呼叫。对于大多<br/>&nbsp;数需要刷新时间的LPmud而言，还是不要定义的好。<br/>****************************************************************************/<br/>&nbsp;#undef LAZY_RESETS</p><p>/****************************************************************************<br/>存盘文件的缺省后缀名。<br/>****************************************************************************/<br/>&nbsp;#define SAVE_EXTENSION “.o”</p><p>/****************************************************************************<br/>下面两个选项使用来控制ansi的用户输入的，这个比较容易模拟出来，因为自由的ansi<br/>输入可能会导致一些显示错误。<br/>****************************************************************************/<br/>&nbsp;#define NO_ANSI<br/>&nbsp;#define STRIP_BEFORE_PROCESS_INPUT</p><p>/****************************************************************************<br/>笔者水平有限，不知道OPC是什么东西。只知道定义以后，可以用一个opcprof()函数来<br/>&nbsp;统计外部函数调用的情况。下面得选项稍有不同，一次只能定义其中的一个。<br/>****************************************************************************/<br/>#undef OPCPROF<br/>#undef OPCPROF_2D</p><p>/****************************************************************************<br/>当这个选项定义以后，当发生crash的时候，master.c中定义的crash()将被呼叫。<br/>****************************************************************************/<br/>&nbsp;#define TRAP_CRASHES</p><p>/****************************************************************************<br/>可以在call_outs中使用this_player()<br/>&nbsp;****************************************************************************/<br/>&nbsp;#define THIS_PLAYER_IN_CALL_OUT</p><p>/****************************************************************************<br/>这个定义是比较有用的，定义以后，call_out将产生一个int序列，这个序列可以方便的<br/>&nbsp;被find_call_out()和remove_call_out()调用。这是一个效率极高的处理方式。原来使<br/>&nbsp;用name来处理的方式相对比较低效。唯一的代价是些许系统开销。<br/>****************************************************************************/<br/>&nbsp;#define CALLOUT_HANDLES</p><p>/****************************************************************************<br/>调试非常有用，一般情况下不需要。<br/>****************************************************************************/<br/>&nbsp;#undef FLUSH_OUTPUT_IMMEDIATELY</p><p>/****************************************************************************<br/>这个定义允许在Lib中给与一些object以特权，除非你非常了解这个定义对于你所要撰写<br/>&nbsp;的Lib的用处，不然的话，不要定义这个。<br/>****************************************************************************/<br/>&nbsp;#undef PRIVS</p><p>/****************************************************************************<br/>下面这个定义可以使互动物件也适用catch_tell()，当然你就必须在user.c中写入catc<br/>&nbsp;h_tell()来处理receive(msg)。<br/>****************************************************************************/<br/>&nbsp;#undef INTERACTIVE_CATCH_TELL</p><p>/****************************************************************************<br/>受限制的ed模式<br/>****************************************************************************/<br/>&nbsp;#define RESTRICTED_ED</p><p>/****************************************************************************<br/>使用下面这个定义，你就不能在想要撰写的Lib中使用shadow，而shadow往往非常有用，<br/>&nbsp;所以除非你明确知道不需要，不然不要定义这个选项。<br/>****************************************************************************/<br/>&nbsp;#undef NO_SHADOWS</p><p>/****************************************************************************<br/>定义下面这个，可以snoop shadowed object，因为shadowed object可能不知道送过来<br/>&nbsp;的msg。<br/>****************************************************************************/<br/>&nbsp;#undef SNOOP_SHADOWED</p><p>/****************************************************************************<br/>这是一个有趣的定义，可以让你监听snooper的msg，也许利用起来比较有趣。当然也可<br/>&nbsp;以不定义它。<br/>****************************************************************************/<br/>&nbsp;#define RECEIVE_SNOOP</p><p>/****************************************************************************<br/>这不是一个非常准确的定义，如果你想知道物件调用函数的时候，使用了多少时间，可<br/>&nbsp;以用这个试试。不过不要对它的准确性基于太多的希望。<br/>****************************************************************************/<br/>&nbsp;#define PROFILE_FUNCTIONS</p><p>/****************************************************************************<br/>‘buffer’这个类型定义的选择，按所要撰写的Lib而定，如果你可能要用到这种变量定义<br/>&nbsp;，就不要定义这个选项。<br/>****************************************************************************/<br/>&nbsp;#undef NO_BUFFER_TYPE</p><p>/****************************************************************************<br/>设置 pragma　’save_binary’　的有效性。<br/>&nbsp;使用这个选项，可以是Lib运行速度有所提高，并且降低系统的开销。代价就是将占用更<br/>&nbsp;多的硬盘空间。<br/>****************************************************************************/<br/>&nbsp;#define BINARIES</p><p>/****************************************************************************<br/>允许定义数组变量，关键字array。比如 int array x = ({…});<br/>不过估计这样定义也不会有人反对 int *x = ({});<br/>定义这个选项与否，主要是看是不是习惯使用array这个声明，如果你来自C或者java，<br/>&nbsp;也许会喜欢的。<br/>****************************************************************************/<br/>&nbsp;#define ARRAY_RESERVED_WORD</p><p>/****************************************************************************<br/>这个同上，关键字ref。按照Lib撰写人的习惯来定义比较好。<br/>****************************************************************************/<br/>&nbsp;#define REF_RESERVED_WORD</p><p>/****************************************************************************<br/>扩充包是可选配件<br/>&nbsp;如果你定义了PACKAGE_XYZZY，那么你可以参看 packages/xyzzy.c　中的函数来确定可<br/>&nbsp;以使用哪些efuns。<br/>&nbsp;确定使用哪些扩充包，主要取决于提供的efuns是否是需要的。</p><p>****************************************************************************/</p><p>/****************************************************************************<br/>这个扩充包的函数还是非常有用的，比如query_ip_port() repeat_string()等等。</p><p>****************************************************************************/</p><p>#define PACKAGE_CONTRIB</p><p>/****************************************************************************<br/>下面这个包主要用来了解driver内部的信息。<br/>****************************************************************************/<br/>&nbsp;#define PACKAGE_DEVELOP</p><p>/****************************************************************************</p><p>****************************************************************************/<br/>&nbsp;#define PACKAGE_MATH</p><p>/****************************************************************************<br/>这个是图像处理包，不过，笔者也没用过。<br/>****************************************************************************/<br/>&nbsp;#undef PACKAGE_MATRIX</p><p>/****************************************************************************<br/>这个包的函数用来了解Mudlib的数据，比较实用。<br/>****************************************************************************/<br/>&nbsp;#undef PACKAGE_MUDLIB_STATS</p><p>/****************************************************************************<br/>呵呵，这个当然非常有用了。<br/>****************************************************************************/<br/>&nbsp;#define PACKAGE_SOCKETS</p><p>/****************************************************************************<br/>这个用处不大，尤其是中文使用者，呵呵<br/>****************************************************************************/<br/>&nbsp;#undef PACKAGE_PARSER</p><p>/****************************************************************************<br/>这个也没什么大的用处。允许driver在config文件里exe()命令清单<br/>****************************************************************************/<br/>&nbsp;#undef PACKAGE_EXTERNAL</p><p>/****************************************************************************<br/>外部扩展指令支持的数目<br/>****************************************************************************/<br/>&nbsp;#ifdef PACKAGE_EXTERNAL<br/>&nbsp;#define NUM_EXTERNAL_CMDS<br/>&nbsp;#endif</p><p>/****************************************************************************<br/>数据库支持包，想用数据库mysql的Lib撰写者比较有用，<br/>****************************************************************************/<br/>&nbsp;//#define PACKAGE_DB<br/>&nbsp;#undef PACKAGE_DB<br/>&nbsp;/****************************************************************************<br/>如果PACKAGE_DB被定义，必须选择下面中的一个来支持数据库<br/>****************************************************************************/<br/>&nbsp;#ifdef PACKAGE_DB<br/>&nbsp;#define USE_MSQL 1 /* MiniSQL, it’s small; it’s free */<br/>&nbsp;#undef USE_MYSQL 2 /* MySQL, bigger; it’s free */<br/>&nbsp;#define DEFAULT_DB USE_MSQL /* default database */<br/>&nbsp;#endif</p><p>/****************************************************************************<br/>　　UID，就是用户有效识别码，国内的LPMud大多基于 wizard 以及 uid 系统，如果不<br/>&nbsp;是新Lib的撰写者，这个是比较有用的。如果你拥有了自己的理念，可以不使用这些定义<br/>&nbsp;。从MudOS开发者来看，他们也没有明确说不需要这些。虽然本人倒是比较喜欢放弃这些<br/>&nbsp;设定，但是这些设定的存在，确实可以方便很多的处理。<br/>&nbsp;如果你打算使用UID，那就定义下面这个选项。<br/>****************************************************************************/<br/>&nbsp;#define PACKAGE_UIDS</p><p>/****************************************************************************<br/>自动设定UID，那就不需要每次都seteuid(getuid(this_object()))。如果需要seteuid<br/>&nbsp;(0)，那么不要定义这个，比如现在大多数的Lib。<br/>****************************************************************************/<br/>&nbsp;#define AUTO_SETEUID</p><p>/****************************************************************************<br/>&nbsp;backbone这个设定是被自动认可的。<br/>****************************************************************************/<br/>&nbsp;#define AUTO_TRUST_BACKBONE</p><p>/****************************************************************************<br/>下面这些设定，一般情况下，不需要做出大的调整。<br/>&nbsp;资源问题，使用32位地址。<br/>****************************************************************************/<br/>&nbsp;#undef USE_32BIT_ADDRESSES</p><p>/****************************************************************************<br/>心跳时间，这里是一秒。<br/>****************************************************************************/<br/>&nbsp;#define HEARTBEAT_INTERVAL 2000000</p><p>/****************************************************************************<br/>&nbsp;call_out的设定<br/>****************************************************************************/<br/>&nbsp;#define CALLOUT_CYCLE_SIZE 64</p><p>/****************************************************************************<br/>信息暂存设定<br/>****************************************************************************/<br/>&nbsp;#define LARGEST_PRINTABLE_STRING 8192</p><p>/****************************************************************************<br/>输出信息buffer设定<br/>****************************************************************************/<br/>&nbsp;#define MESSAGE_BUFFER_SIZE 65536</p><p>/****************************************************************************<br/>定义call_other cache的bits number<br/>&nbsp;6 64 1k<br/>&nbsp;8 256 4k<br/>&nbsp;10 1024 16k<br/>&nbsp;12 4096 64k<br/>&nbsp;14 16384 256k<br/>&nbsp;16 65536 1M<br/>&nbsp;****************************************************************************/<br/>&nbsp;#define APPLY_CACHE_BITS 12</p><p>/****************************************************************************<br/>&nbsp;call_other的cache统计<br/>****************************************************************************/<br/>&nbsp;#define CACHE_STATS</p><p>/****************************************************************************<br/>不定义可以快一点。<br/>****************************************************************************/<br/>&nbsp;#undef TRACE</p><p>/****************************************************************************<br/>&nbsp;LPC-&gt;C的编译<br/>****************************************************************************/<br/>&nbsp;#undef LPC_TO_C</p><p>/****************************************************************************<br/>看系统而定，一般不需要定义。<br/>****************************************************************************/<br/>&nbsp;#undef RUNTIME_LOADING</p><p>/****************************************************************************<br/>这个定义以后，允许被跟踪执行。<br/>****************************************************************************/<br/>&nbsp;#undef TRACE_CODE</p><p>/****************************************************************************<br/>缺省设定是32，主要关系到 heart_beat 的系统开销。<br/>****************************************************************************/<br/>&nbsp;#define HEART_BEAT_CHUNK 64</p><p>/****************************************************************************<br/>一般情况下，get_char不是bufferd。所以不太必要定义这个选项。<br/>****************************************************************************/<br/>&nbsp;#undef GET_CHAR_IS_BUFFERED</p><p>/****************************************************************************<br/>字符串定义。<br/>****************************************************************************/<br/>&nbsp;#define SMALL_STRING_SIZE 100<br/>&nbsp;#define LARGE_STRING_SIZE 1000</p><p>/****************************************************************************<br/>指令buffer定义。<br/>****************************************************************************/<br/>&nbsp;#define COMMAND_BUF_SIZE 2000</p><p>/****************************************************************************<br/>呵呵，如果dbase深度超过了25就会溢出，这个设定就是这里定义的。当年最常见的一个<br/>&nbsp;当机bug就是set指令的dbase溢出导致的。<br/>****************************************************************************/<br/>&nbsp;#define MAX_SAVE_SVALUE_DEPTH 50</p><p>/****************************************************************************<br/>&nbsp;25个局部变量调用，对于一个函数来说，应该是够了。数数COMBAT_D中的attack()函数<br/>&nbsp;用到了几个局部变量。本人曾经定义超过25个变量，结果导致出错，但是那个时候不知<br/>&nbsp;道为什么，虽然预感到这一点，可以在mud配置文件中定义。<br/>****************************************************************************/<br/>&nbsp;#define CFG_MAX_LOCAL_VARIABLES 100<br/>&nbsp;#define CFG_EVALUATOR_STACK_SIZE 2000<br/>&nbsp;#define CFG_MAX_CALL_DEPTH 100</p><p>/****************************************************************************<br/>下面定义的必须选择 4, 16, 64, 256, 1024, 4096 中的一个数字<br/>****************************************************************************/<br/>&nbsp;#define CFG_LIVING_HASH_SIZE 1024</p><p>/****************************************************************************<br/>&nbsp;NEXT_MALLOC_DEBUG: define this if using a NeXT and you want to enable<br/>&nbsp;the malloc_check() and/or malloc_debug() efuns. Run the ‘man malloc_debug’<br/>command on the NeXT to find out what the arguments to malloc_debug(int)<br/>&nbsp;mean. The malloc_check() efun calls the NeXT NXMallocCheck() system<br/>&nbsp;call which does a consistency check on malloc’s data structures (this<br/>&nbsp;consistency check is done at each malloc() and free() for certain<br/>&nbsp;malloc_debug() levels). A non-zero return value indicates there was<br/>&nbsp;a consistency problem. For those NeXT users wanting a bit more<br/>&nbsp;performance out of malloc, try defining NEXT_MALLOC_DEBUG and calling the<br/>&nbsp;malloc_debug(-1) efun (with an arg of -1). This will turn all<br/>&nbsp;malloc debugging off and call malloc_singlethreaded() which the NeXT<br/>&nbsp;malloc man page claims can make NeXT system malloc 10% to 15% faster.</p><p>[NOTE: This #define has no affect on the driver if not using the<br/>&nbsp;NeXTSTEP OS.]</p><p>Warning: if you use a NeXT and define NEXT_MALLOC_DEBUG, be sure to<br/>&nbsp;protect the use of the malloc_check() and malloc_debug() efuns<br/>&nbsp;since setting certain debug levels can cause malloc() and free()<br/>&nbsp;to become _very_ slow (protect efuns by using simul_efuns and<br/>&nbsp;valid_override).</p><p>[NOTE: malloc_debug(6) is a good compromise between efficiency and<br/>&nbsp;completeness of malloc debugging (malloc/free will be about half as fast).]<br/>&nbsp;****************************************************************************/<br/>&nbsp;#define NEXT_MALLOC_DEBUG</p><p>#endif</p><p>编译V14的时候编译DB<br/>&nbsp;option.h修改下列配置<br/>#define PACKAGE_DB<br/>&nbsp;#ifdef PACKAGE_DB<br/>&nbsp;#undef USE_MSQL /* MiniSQL, it’s small; it’s free */<br/>&nbsp;#define USE_MYSQL 2 /* MySQL, bigger; it’s free */<br/>&nbsp;#define DEFAULT_DB USE_MYSQL /* default database */<br/>&nbsp;#endif</p><p>修改 db.h 头文件：<br/>&nbsp;将 24 行至 37 行注释掉，紧接着写上你自己的 MySQL 头文件的位置，<br/>find / -name mysql.h 就找到了！<br/>&nbsp;例如在 /usr/local/mysql/include/mysql.h<br/>就写上：<br/>#include “/usr/local/mysql/include/mysql.h”</p><p>在源代码目录里的 system_libs 文件里加上 mysql 连接库的位置，<br/>&nbsp;例如在 /usr/local/mysql/lib<br/>就加上：<br/>-L/usr/local/mysql/lib -lmysqlclient</p><p></p>]]></description><category>Mud</category><comments>http://www.xiaqiang.com.cn/post/13.html#comment</comments><wfw:commentRss>http://www.xiaqiang.com.cn/feed.asp?cmt=13</wfw:commentRss></item><item><title>ANSI 颜色使用研究</title><author>null@null.com (xiaqiang)</author><link>http://www.xiaqiang.com.cn/post/12.html</link><pubDate>Fri, 19 Jul 2013 10:26:06 +0800</pubDate><guid>http://www.xiaqiang.com.cn/post/12.html</guid><description><![CDATA[<p>　　众所周知，ES2类的LPMUD是一个只有文字的世界，因为没有任何图像，所以正是因为有16种ANSI颜色，才使得&nbsp;我们这个世界变得丰富多彩，更有吸引力。出于一名巫师和一名网页制作者的考虑，目前的巫师在使用ANSI颜色时，常常不是惜墨如金一点都不用就是不分场合到处乱用，这样对于一个MUD的表现力而言都是不好的。所以我今天有空&nbsp;就想随便说说有关ANSI&nbsp;COLOR的一些使用方法，给大家参考。&nbsp;<br />　　我们先从源头说起，之所以加了ANSI标示符的字符就可以显示不同的颜色，是因为通过客户端像zMUD这样的软件，能够从Winsock控件的DataArrival事件中传回的数据中识别出ANSI标示符，将其后面的字符转换成指定的颜色，在RichTextbox中显示出来。这涉及一些简单的Windows网络编程，就不多谈了。至于tintin+这些，虽然在Linux下使用的控件和Windows不同，但原理还是一样的。&nbsp;<br />　　一般来说，要在一个程序中使用ANSI颜色，人人都知道要在头上#include&nbsp;，那么，这个“ansi.h”文件你打开看过了没有呢？在一些welcome文件中那些初学者看来非常深奥的什么[1;37m这样的字符你明白了它的意思没有呢？让我们打开/include/ansi.h这个文件看一看吧：&nbsp;</p><p>//&nbsp;File&nbsp;:&nbsp;/include/ansi.h&nbsp;<br />//&nbsp;这是MUDLIB的标准颜色设置，由Jjgod汉化&nbsp;</p><p>#define&nbsp;ESC&nbsp;&quot;&quot;&nbsp;<br />#define&nbsp;CSI&nbsp;ESC&nbsp;+&nbsp;&quot;[&quot;&nbsp;</p><p>&nbsp;</p><p>#define&nbsp;BLK&nbsp;ESC+&quot;[30m&quot;&nbsp;&nbsp;<br />#define&nbsp;RED&nbsp;ESC+&quot;[31m&quot;&nbsp;&nbsp;<br />#define&nbsp;GRN&nbsp;ESC+&quot;[32m&quot;&nbsp;&nbsp;<br />#define&nbsp;YEL&nbsp;ESC+&quot;[33m&quot;&nbsp;&nbsp;<br />#define&nbsp;BLU&nbsp;ESC+&quot;[34m&quot;&nbsp;&nbsp;<br />#define&nbsp;MAG&nbsp;ESC+&quot;[35m&quot;&nbsp;&nbsp;<br />#define&nbsp;CYN&nbsp;ESC+&quot;[36m&quot;&nbsp;&nbsp;<br />#define&nbsp;WHT&nbsp;ESC+&quot;[37m&quot;&nbsp;&nbsp;</p><p>&nbsp;</p><p>#define&nbsp;HIR&nbsp;ESC+&quot;[1;31m&quot;&nbsp;&nbsp;<br />#define&nbsp;HIG&nbsp;ESC+&quot;[1;32m&quot;&nbsp;&nbsp;<br />#define&nbsp;HIY&nbsp;ESC+&quot;[1;33m&quot;&nbsp;&nbsp;<br />#define&nbsp;HIB&nbsp;ESC+&quot;[1;34m&quot;&nbsp;&nbsp;<br />#define&nbsp;HIM&nbsp;ESC+&quot;[1;35m&quot;&nbsp;&nbsp;<br />#define&nbsp;HIC&nbsp;ESC+&quot;[1;36m&quot;&nbsp;&nbsp;<br />#define&nbsp;HIW&nbsp;ESC+&quot;[1;37m&quot;&nbsp;&nbsp;</p><p>&nbsp;</p><p>#define&nbsp;HBRED&nbsp;ESC+&quot;[41;1m&quot;&nbsp;&nbsp;<br />#define&nbsp;HBGRN&nbsp;ESC+&quot;[42;1m&quot;&nbsp;&nbsp;<br />#define&nbsp;HBYEL&nbsp;ESC+&quot;[43;1m&quot;&nbsp;&nbsp;<br />#define&nbsp;HBBLU&nbsp;ESC+&quot;[44;1m&quot;&nbsp;&nbsp;<br />#define&nbsp;HBMAG&nbsp;ESC+&quot;[45;1m&quot;&nbsp;&nbsp;<br />#define&nbsp;HBCYN&nbsp;ESC+&quot;[46;1m&quot;&nbsp;&nbsp;<br />#define&nbsp;HBWHT&nbsp;ESC+&quot;[47;1m&quot;&nbsp;&nbsp;</p><p>&nbsp;</p><p>#define&nbsp;BBLK&nbsp;ESC+&quot;[40m&quot;&nbsp;&nbsp;<br />#define&nbsp;BRED&nbsp;ESC+&quot;[41m&quot;&nbsp;&nbsp;<br />#define&nbsp;BGRN&nbsp;ESC+&quot;[42m&quot;&nbsp;&nbsp;<br />#define&nbsp;BYEL&nbsp;ESC+&quot;[43m&quot;&nbsp;&nbsp;<br />#define&nbsp;BBLU&nbsp;ESC+&quot;[44m&quot;&nbsp;&nbsp;<br />#define&nbsp;BMAG&nbsp;ESC+&quot;[45m&quot;&nbsp;&nbsp;<br />#define&nbsp;BCYN&nbsp;ESC+&quot;[46m&quot;&nbsp;&nbsp;<br />//&nbsp;#define&nbsp;BWHT&nbsp;ESC+&quot;[47m&quot;&nbsp;&nbsp;</p><p>#define&nbsp;NOR&nbsp;ESC+&quot;[2;37;0m&quot;&nbsp;&nbsp;</p><p>&nbsp;<br />&nbsp;<br />&nbsp;</p><p>#define&nbsp;BOLD&nbsp;ESC+&quot;[1m&quot;&nbsp;&nbsp;<br />#define&nbsp;CLR&nbsp;ESC+&quot;[2J&quot;&nbsp;&nbsp;<br />#define&nbsp;HOME&nbsp;ESC+&quot;[H&quot;&nbsp;&nbsp;<br />#define&nbsp;REF&nbsp;CLR+HOME&nbsp;&nbsp;<br />#define&nbsp;BIGTOP&nbsp;ESC+&quot;#3&quot;&nbsp;&nbsp;<br />#define&nbsp;BIGBOT&nbsp;ESC+&quot;#4&quot;&nbsp;&nbsp;<br />#define&nbsp;SAVEC&nbsp;ESC+&quot;[s&quot;&nbsp;&nbsp;<br />#define&nbsp;REST&nbsp;ESC+&quot;[u&quot;&nbsp;&nbsp;<br />//#define&nbsp;REVINDEX&nbsp;ESC+&quot;M&quot;&nbsp;&nbsp;<br />#define&nbsp;SINGW&nbsp;ESC+&quot;#5&quot;&nbsp;&nbsp;<br />#define&nbsp;DBL&nbsp;ESC+&quot;#6&quot;&nbsp;&nbsp;<br />#define&nbsp;FRTOP&nbsp;ESC+&quot;[2;25r&quot;&nbsp;&nbsp;<br />#define&nbsp;FRBOT&nbsp;ESC+&quot;[1;24r&quot;&nbsp;&nbsp;<br />#define&nbsp;UNFR&nbsp;ESC+&quot;[r&quot;&nbsp;&nbsp;<br />#define&nbsp;BLINK&nbsp;ESC+&quot;[5m&quot;&nbsp;&nbsp;<br />#define&nbsp;U&nbsp;ESC+&quot;[4m&quot;&nbsp;&nbsp;<br />#define&nbsp;REV&nbsp;ESC+&quot;[7m&quot;&nbsp;&nbsp;<br />#define&nbsp;HIREV&nbsp;ESC+&quot;[1,7m&quot;&nbsp;&nbsp;</p><p>　　上面就是经过我汉化的的ansi.h文件了，其中有些实在太难译，所以我只好把原来的留了下来。认真看过上面&nbsp;的这些，就应该基本明白常用的ANSI颜色怎么用了，所以说，如果不#include&nbsp;，照样也可以用彩色，&nbsp;你只需要在用的前面加上[1;33m这样就行了，这些都很简单，我就不赘述了。这篇文章要谈的重点，其实是一个A&nbsp;NSI&nbsp;COLOR于zMUD的协调问题。&nbsp;<br />　　基本上绝大多数的MUD玩家都是使用zMUD为客户端软件的，所以你的程序在zMUD中的显示效果就尤为重要了。问题其实是出现在了在ANSI颜色的使用上，zMUD和标准的ANSI定义出现了分歧，这种分歧是在zMUD&nbsp;4.62汉化版后产生的，zMUD的4.62英文版都应该尚无此问题，但正是因为以前没有问题后来才出现了问题。你听到这里是不是越来越不明白？那好，我们还是从源头说起吧。下面的“原先”，就是指zMUD&nbsp;4.62&nbsp;英文版及以前的。&nbsp;<br />　　看过上面的定义就应该清楚[1;xxm这样的定义，也就是HIX这样的定义中，那个&quot;1;&quot;或者&quot;HI&quot;什么的，是表示粗体的意思，原先的注释中说得清清楚楚的，而原先的YEL，也就是[33m，大概是这种亮度，而倘若变成了HIY或者说[1;33m的话，就应该是这样了，这才是标准的用法，而zMUD对中文字体的支持还是不大完善，一般来说就是使用宋体，假如出现了粗体，也会在屏幕上划得斑驳陆离，本来是这一行的字，滑到了下面几行去，非常的有碍观瞻。&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;所以以zMUD4.62英文版为预览工具来写的程序一般是不用HIY而是就用YEL的，因为这样颜色也够亮，显示也没有问题，一切都很好。&nbsp;<br />　　但到了4.62汉化版以后，就破坏了这个格局。在这个版本以后的所有zMUD，基本上都是将[1;也就是HI默认解释为高亮，而原来的YEL什么的，就变得很是暗淡了，比如此版本以后的YEL，显示出来是这样，而HIY呢，就是这样了，因为始终不出现粗体，所以自然也没有显示的问题。而在原来的那种环境下开发出来的程序可就惨了，像我的模拟华附，整个MUD的颜色都显得十分暗淡，自然很不具亲和力了。&nbsp;<br />　　本身问题是很容易解决的，只要调整一下zMUD的设置就可以了，但问题在于有关颜色的zMUD设置由特别难调整（差不多每个版本我的试过），造成了本身正常的设置还要迁就不正常的设置了，绝大部分的玩家都不会去调整。因此的你的MUD如果要使用Ansi颜色就要考虑这个兼容性问题了。<br />　　所以呢，因为绝大部分的MUD玩家使用的都是zMUD&nbsp;4.62中文版以上的，我建议还是统一使用“HIX”这种好一点，玩家看起来颜色比较鲜亮，同时也没有粗体显示不清的问题。低亮度的颜色就少用一些吧，当然，假如你已经全部使用了低亮度或者高亮度，想转换的话，也可以通过改ansi.h来实现，这比较简单，就不用我说了吧。&nbsp;<br />　　其实ansi.h还是有很多没有普遍使用的妙处的，这就有待各位自己去发现了。</p>]]></description><category>Mud</category><comments>http://www.xiaqiang.com.cn/post/12.html#comment</comments><wfw:commentRss>http://www.xiaqiang.com.cn/feed.asp?cmt=12</wfw:commentRss></item><item><title>金庸武侠年表-清朝以前</title><author>null@null.com (xiaqiang)</author><link>http://www.xiaqiang.com.cn/post/11.html</link><pubDate>Wed, 23 Jan 2013 12:25:35 +0800</pubDate><guid>http://www.xiaqiang.com.cn/post/11.html</guid><description><![CDATA[<p>&nbsp;原作者&nbsp;<a href="http://www.mudbuilder.com/u.php?uid=2">lonely</a>&nbsp;</p><p>背景知识，分享一下，供武侠mud做任务参考用<br /><br />1092年，《天龙八部》故事开始。秋季，段誉参加无量剑比斗。后结识钟灵、木婉清等。<br />《〈天龙八部〉释名》：“本书故事发生于北宋哲宗元佑、绍圣年间，公元一○九四年前后。”《天龙八部》第6章：“是时北宋汴梁哲宗天子在位，年岁尚幼，太皇太后高氏垂帘听政。……保定帝在位十一年，改元三，曰保定、建安、天佑，其时正当天估年间，四境宁静，国泰民安。”按北宋哲宗元佑为1086—1093年，而大理天佑元年为公元1090年，则故事开始时约在1090年或稍晚。<br /><br />1093年，年初，段誉为鸠摩智所擒，三月中被掳至江南。于无锡与乔峰结拜。<br />第11章《向来痴》：“他虽无处世经历，但这二十余日来，对此事早已深思熟虑，想明白了其中关窍……自此一路向东，又行了二十余日，段誉听着途人的口音，渐觉清雅绵软，菜肴中也没了辣椒。……这时正是三月天气，杏花夹径，绿柳垂湖，暖洋洋的春风吹在身上，当真是醺醺欲醉。”<br />本年，乔峰为查明身份，离杏子林后先后赴少林、聚贤庄、雁门关、信阳，后，因中马夫人计，于小镜湖误杀阿朱，伤心离中原而出关。<br /><br />1094年，二月初八，擂鼓山珍珑棋会，虚竹得无涯子功力，此后辗转得遇天山童姥、李秋水，终成天山灵鹫宫之主。<br />29章：“段誉接过一看，见帖上写着四行字道：‘苏星河奉请天下精通棋艺才俊，于二月初八日驾临河南擂鼓山天聋弈棋。’”<br /><br />本年，六月十五，少林寺大会。萧远山、慕容博现身，后被无名僧点化，皈依佛门。<br />40章：“各人都接到丐帮帮主庄聚贤的英雄帖，说道少林寺和丐帮向来并峙中原，现庄聚贤新任丐帮帮主，意欲立一位中原的武林盟主，并定下若干规章，以便同道一齐遵守，定六月十五亲赴少林寺，与玄慈方丈商酌。”<br /><br />本年，八月中秋，西夏招驸马，虚竹寻得梦姑。<br />40章：“公冶乾颇识诸国文字，从头至尾看了一遍，说道：‘果然是西夏国王招驸马的榜文。文中言道：西夏国文仪公主年将及笄，国王要征选一位文武双全、俊雅英伟的未婚男子为驸马，定放今年八月中秋起选拔，不论何国人士，自信为天下一等一人才者，于该日之前投文晋谒，国王皆予优容接见。即令不中驸马之选，亦当量才录用，授以官爵，更次一等者赏以金银……’”<br />本年十月，段正淳及其情侣殒于曼陀山庄。<br />本年，北宋哲宗元佑九年，太皇太后驾崩，哲宗改元绍圣。耶律洪基伺机征宋，为萧峰所阻。萧自尽，《天龙八部》结束。<br /><br />1115年，北宋政和五年，黄裳刻道藏。数年后成武功高手。<br />《射雕英雄传》后记：“《射雕英雄传》中所说的黄裳真有其人。近人陈国符先生《道藏源流考》中考证宋徽宗访求天下道教遗书刻板的经过颇详。徽宗于政和三年下诏天下访求道教仙经，所获甚众。政和五年设经局，敕道士校定，送福州闽县，由郡守黄裳役工镂板。所刊道藏称为《政和万寿道藏》，共五百四十函，五千四百八十一卷。”<br />黄裳，字晟仲，人称演山先生，福建延平人，高宗建炎三年（1042—1129）卒，年八十七。<br />独孤求败（1100？－1170年），生年不详，死于公元1170年<br /><br /><br />1180——1190年间，某年中秋，少林寺武功考校中，火工头陀击毙达摩堂首座苦智禅师，寺中内讧，罗汉堂首座苦慧禅师忿而出走开创西域少林。<br />详见《倚天屠龙记第2章。文中时间为郭襄19岁游少林，其时为1263年，而“七十余年前”则在1180——1190年间。<br /><br /><br />1200年，首次华山论剑。<br /><br />1204年，《射雕》故事开始。<br /><br />1205年，郭靖出生。<br /><br />1223年，中秋嘉兴烟雨楼之会，郭靖18岁。穆念慈怀杨过。<br /><br />1224年，杨过出生。<br />《射雕》中农历七月十五日是丐帮君山大会，而郭靖和黄蓉在七天后（即七月二十二日）至铁掌峰并见到杨康、穆念慈。穆念慈正是在此期间有了杨过。以正常十月怀胎计算，杨过生于次年农历五月间。<br /><br />&nbsp;&nbsp;1225年，郭靖、黄蓉南下途经江西上饶，救穆念慈，为杨过起名。成吉思汗逝世。二次华山论剑。《射雕英雄传》结束。<br /><br />1238年，杨过14岁，被郭靖、黄蓉夫妇收留。以不见容于桃花岛，被郭靖送往终南山重阳宫学艺。其后机缘巧合，入古墓结识小龙女。此时小龙女20岁。<br /><br />1242年，杨过18岁，在古墓生活3年有余。后与龙出秘道，在终南山学习王重阳留下的《九阴真经》。<br /><br />1243年，杨过19岁，先后结识陆无双与程英，并于华山见到洪七公与欧阳峰。<br /><br />1244年，郭襄出生。杨过20岁，与小龙女分别于绝情谷。<br />1246年，张君宝（三丰）出生。<br />《倚天屠龙记》第3章：……一路上虽然桃红柳绿，春色正浓，他却也无心赏玩，心中默默计算：‘今日三月廿四，到四月初九还有一十四天，须得道上丝毫没有耽搁，方能及时赶到武当山，祝贺恩师他老人家九十岁大寿。’”<br />1259年，襄阳大战，郭襄16岁。《神雕侠侣》结束。<br />《神雕侠侣》第39章：“自蒙古和宋军交锋以来，从未有如此大败，而一国之主丧于城下，更是军心大沮。蒙古大汗之位并非父死子袭，系由皇族王公、重臣大将会议拥立。蒙哥既死，其弟七王子阿里不哥在北方蒙古老家被得王公拥戴而为大汗。忽必烈得讯后领军北归，与阿里不哥争位，兄弟各率精兵互斗。最后忽必烈得胜，但蒙古军已然大伤元气，无力南攻，襄阳城得保太平。直到一十三年后的宋度宗咸淳九年，蒙古军始再进攻襄阳。”按，南宋度宗咸淳九年为公元1273年。<br />1263年，郭襄19岁，游历少林，结识何足道。张君宝逃出少林寺。<br />《倚天屠龙记》第1章：“郭襄自和杨过、小龙女夫妇在华山绝顶分手后，三年来没得到他二人半点音讯。”<br />1285年，南宋淳佑五年，郭襄40岁，创立峨眉派。<br />1336年，《倚天屠龙记》新故事开始。<br />《倚天屠龙记》第3章：“这一年是元顺帝至元二年，宋朝之亡至此已五十余年。”<br />1346年，张无忌9岁，随父母自冰火岛返回中原。<br />《倚天屠龙记》第8章&nbsp;穷发十载始归航。<br />1348年，张无忌11岁，下随张三丰下武当山求医。<br />《倚天屠龙记》第18章：“他瞧着这位相别九年的六师叔时，只见他满脸风尘之色，两鬓微见斑白，想是纪晓芙之死于他心灵有极大打击。”<br />1352年，张无忌15岁，被困昆仑仙境，得《九阳真经》。<br />《倚天屠龙记》第17章：“他进来时十五岁，身子尚小，出去已是二十岁，长大成人，却钻不过那狭窄的洞穴了。他吸一口气，运起了缩骨功，全身骨骼挤拢，骨头和骨头之间的空隙缩小，轻轻易易的便钻了过去。”<br />1357年，张无忌20岁，习得九阳神功，解光明顶之围，任明教教主。<br /><br />1358年，韩林儿死。张无忌归隐。《倚天屠龙记》结束。<br /><br />1428年左右，日月神教夜袭武当山。<br />《倚天屠龙记》结束时张无忌21岁，杨不悔约16岁。两人的影响力比较合理的估计是70年左右（误差不超过10年），此时张无忌超过90岁，杨也年过八旬。而《倚天屠龙记》中少林大会上，殷梨亭下场斗周芷若时，杨不悔已怀孕。武当七侠的后辈中最杰出的宋青书已死，则殷杨之后人很有可能继承武当衣钵或杨逍武功，凭与张无忌的关系或许还可能得张真传，实力也不容小视。故此，不仅需要张无忌、杨不悔等人老迈或身故，而且要待其直系徒弟或子嗣的影响力衰减时，日月神教才可能发动攻击。<br /><br />1484年，华山派气宗、剑宗决战于玉女峰，气宗胜出，剑宗高手伤亡殆尽。此后五年内，岳不群继任华山派掌门。<br />《笑傲江湖》第9回：“岳不群在石上坐下，缓缓的道：‘二十五年之前，本门功夫本来分为正邪两途。’”《笑傲江湖》第11回：“那封不平大声道：‘你篡夺华山派掌门之位，已二十多年啦，到今天还做不够？应该让位了罢？’师父笑道：‘各位大动阵仗的来到华山，却原来想夺在下这掌门之位。那有甚么希罕？封兄如自忖能当这掌门，在下自当奉让。’那封不平道：‘当年你师父凭着阴谋诡计，篡夺了本派掌门之位，现下我已禀明五岳盟主左盟主，奉得旗令，来执掌华山一派。’”又：“岳不群道：‘成兄，你们“剑宗”一支，二十五年前早已离开本门，自认不再是华山派弟子，何以今日又来生事？倘若你们自认功夫了得，不妨自立门户，在武林中扬眉吐气，将华山派压了下来，岳某自也佩服。今日这等噜唆不清，除了徒伤和气，更有何益？’”&nbsp;<br /><br /><br />令狐冲慢慢坐了下来，道：“我是个无父无母的孤儿，十五年前蒙恩师和师母收录门下，那时小师妹还只三岁，我比她大得多，常常抱了她出去采野果、捉兔子。我和她是从小一块儿长大的。师父师母没儿子，待我犹似亲生儿子一般，小师妹便等于是我的妹子。”<br /><br />第三十章&nbsp;&nbsp;密议<br />1509年，《笑傲江湖》故事开始。春，福威镖局为青城派灭门。令狐冲约25岁，被罚面壁一年。<br />《笑傲江湖》第1回：“林震南忽道：‘娘子，你今年三十九岁罢？’王夫人啐道：‘呸！这当儿还来问我的年纪？我是属虎，你不知道我几岁吗？’林震南道：‘我发帖子出去，便说是给你做四十岁的大生日……’王夫人道：‘为甚么好端端给我添上一岁年纪？我还老得不够快么？’”王夫人属虎，在《笑傲江湖》开始时39岁，可见当年为蛇年。正德年间共有两个蛇年，即正德四年和正德十六年。据金庸新修订版的介绍，故事发生在明正德年间。而正德十六年正德皇帝就驾崩了，可排除正德十六年为故事发生第一年的可能。如此则《笑傲江湖》故事发生的第一年为正德四年即公元1509年。<br /><br />1510年，夏，令狐冲结识向问天，以营救任我行被囚梅庄地牢。十二月十五聚群雄围少林。<br />1511年，三月十五，五岳剑派并派。日月神教归还武当书剑。<br />1514年，令狐与盈盈成亲。<br />1515年，暮春，《笑傲江湖》故事结束。<br /><br />1563年，《侠客行》故事发生。<br />《侠客行》13章中石清言道：“那是三十年前的事了，他二人那时尚是少年。各门派帮会的首脑接到铜牌请柬之人依约前往，自是无事，否则他这一门派或是帮会不免大祸临头，当时便问：‘到底去是不去？’最先接到铜牌请柬的，是川西青城派掌门人旭山道长。他长笑之下，将两块铜牌抓在手中，运用内力，将两块铜牌熔成了两团废铜。这原是震烁当时的独步内功……”《笑傲江湖》中青城派几乎全军覆没，但《侠客行》故事发生的30年前青城派又出现了顶尖高手旭山道长。余沧海之徒皆以“人”字排行，旭山道长当是其徒孙辈，当在《笑傲江湖》结束后二三十年。所以《侠客行》当在《笑傲江湖》后约五六十年，即明代后期隆庆万历年间（1563—1620）。《侠客行》第19章：“……只见簿面上写着‘河北通州聂家拳‘七字，打开簿子，第一行触目惊心，便是‘庚申五月初二，聂宗台在沧州郝家庄奸杀二命，留书嫁祸于黑虎寨盗贼’，第二行书道：‘庚申十月十七，聂宗峰在济南府以小故击伤刘文质之长子，当夜杀刘家满门一十三人灭口。’”&nbsp;明末的庚申年有1560年和1620年。而1620年华山派已有穆人清等高手，故此“庚申”只能是1560年。第19章：“……姓白的倘若早得几年见了这本帐簿，侠客岛就是对他手下留情，姓白的也要杀他全家。”从白自在之言可知，聂氏灭门在几年前，则《侠客行》故事发生在1560—1570年间。而第20章记载转年有闰二月。查此段时间仅1564年有闰二月。则《侠客行》发生于前一年即1563年。<br /><br /><br />1633年，《碧血剑》故事开始，袁承志10岁。<br /><br />1643年，袁承志20岁，初下华山。<br />《碧血剑》第3回：“这时已是崇祯十六年，袁承志也已二十岁了。这十年之间，袁承志所练华山本门的拳剑内功，与日俱深，天下事却已千变万化，眼下更是如沸如羹，百姓正遭逢无穷无尽的劫难。”<br /><br />1644年，崇祯十七年三月，李自成攻陷北京。明朝灭亡。<br /><br />本年四月，华山弟子集会，《碧血剑》结束。<br />《碧血剑》第19回：“袁承志见封皮上写着‘字谕诸弟子’字样，认得是师父笔迹，先作了一揖，然后恭恭敬敬的接过来，抽出信纸，见信上写道：‘吾华山派历来门规，不得在朝居官任职。今闯王大业克就，吾派弟子功成身退，其于四月月圆之夕，齐集华山之巅。’下面签着个‘清’字。”&nbsp;</p>]]></description><category>Mud</category><comments>http://www.xiaqiang.com.cn/post/11.html#comment</comments><wfw:commentRss>http://www.xiaqiang.com.cn/feed.asp?cmt=11</wfw:commentRss></item></channel></rss>
