<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>德洪</title>
    <description>Email＆MSN：dehongliu@gmail.com
QQ：26728407
欢迎交流</description>
    <link>http://sofire.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>phpdoc文档格式</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/120007" style="color:red;">http://sofire.javaeye.com/blog/120007</a>&nbsp;
          发表时间: 2007年09月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Phpdocumentor文档的阅读笔记<br /><br />把 PhpDocumentor/phpDocumentor/Converter.inc 的4209行的<br />$this->class_data->append('consts',array_merge(<br />改成了<br />$this->page_data->append('consts',array_merge(<br />不知道对不对<br /><br /><pre name="code" class="java">
&lt;?php

//----- 文档块 ----------------------------
/**
 * 以 / ** 开头的注释是一个文档块(DocBlock)
 */

function a0() {}

//----- 文档块描述细节 --------------------

// 文档块包括哪些？
/**
 * 文档块按顺序包括3个部分
 * 1. 短描述
 * 2. 长描述
 * 3. tag段
 */

function a1() {}

//比如
/**
 * 短描述
 *
 * 这是一个长描述。
 * 继续长描述。
 * 如果短描述超过3行，则会只去第一行，作为短描述。
 *
 * 另起一段：因为上面的空行
 */

function a2() {}
// &lt;p>的例子
/**
 * 短描述
 *
 * &lt;p>这是一个长描述。
 * 继续长描述。
 * 用p标签包围的长描述&lt;/p>
 * &lt;p>另起一段&lt;/p>
 * &lt;p>再另起一段&lt;/p>
 */
function a3() {}

/**
 * phpdoc 不支持html的标签，但是可以用下面的几个标签(注意加&lt;>)
 * 
 * b -- &lt;b> 加粗 &lt;/b>
 *
 * br -- 换行，&lt;br>可能被某些转换器忽略 &lt;br>
 *
 * i -- &lt;i> 斜体 &lt;/i>
 *
 * kbd -- &lt;kbd> 标示 键盘输入/屏幕输出 &lt;/kbd>
 *
 * ul -- 没有顺序的列表
 *
 * li -- 列表项
 *
 * ol -- 顺序列表
 *
 * p -- 如果成对使用，则表明一个段，否则只是一个字符串&lt;p>
 * &lt;p>这是一个段&lt;/p>
 *
 * pre -- 
 * &lt;pre>原样输出，即使是各种标签&lt;b>加粗&lt;/b>，相当于XML的CDATA
 * 注意输出成HTML后，会有效果
 * &lt;/pre>
 *
 * var -- 变量名
 *
 * samp -- 非php的示例
 *
 * &lt;code> 加粗 &lt;/code>
 *
 * 不要把这些标签想成是字符串，它们应解析器的不同，而被解析成各种形式
 * 如：b标签在DocBook中是&lt;emphasis>，p标签在PDF中是4个空格
 * 这些都在模板的options.ini文件中定义
 *
 * 要显示带前后尖括号的b标签，可以用《《XXX》》(小写尖括号), 如&lt;&lt;b>>
 *
 * 要用@标签，如果行的开头，则用\@，其他地方不需要加反斜杠 \
 * 如：
 *
 * &lt;code>
 * \@return abc
 * 这是一个标签 @name
 * &lt;/code>
 */ 

function a4() {}

/**
 * 简单的列表(不允许嵌套，因为它不再简单)
 *
 * 这是一个简单的列表(以-、+、#、o)
 * - item 1
 * - item 2, this one
 *   is multi-line
 * 这是一个简单的列表(以-、+、#、o)
 * + item 1
 * + item 2
 * 这是一个简单的列表(以-、+、#、o)
 * # item 1
 * # item 2
 * 这是一个简单的列表(以-、+、#、o)
 * o item 1
 * o item 2
 * 列表结束。下面是顺序列表(以数字开头)
 * 1 ordered item 1
 * 2 ordered item 2
 * 列表结束。下面是还是顺序列表(以数字开头，并且有个点)
 * 1. ordered item 1
 * 2. ordered item 2
 */
function a5() {}

/**
 * 有嵌套的列表
 *
 * 使用ul li ol等标签创建复杂的嵌套列表
 * &lt;ul>
 * &lt;li>outer item 1&lt;/li>
 * &lt;li>outer item 2, this one
 *   is multi-line&lt;/li>
 * &lt;li>item 3 is a nested inner list
 * &lt;ul>
 * &lt;li>inner item 1&lt;/li>
 * &lt;li>inner item 2&lt;/li>
 * &lt;/ul>
 * &lt;li>outer item 4&lt;/li>
 * &lt;/ul>
 */
function a6() {}

/**
 * 在todo标签中的列表
 * @todo My Simple TODO List
 *     - item 1
 *     - item 2
 *     - item 3
 *      - item 3
 * @todo My Complex TODO List
 *     &lt;ol>
 *       &lt;li>item 1.0&lt;/li>
 *       &lt;li>item 2.0&lt;/li>
 *       &lt;li>item 3.0&lt;/li>
 *       &lt;li>
 *         &lt;ol>
 *           &lt;li>item 3.1&lt;/li>
 *           &lt;li>item 3.2&lt;/li>
 *         &lt;/ol>
 *       &lt;li>
 *       &lt;li>item 4.0&lt;/li>
 *     &lt;/ol>
 */
function a7() {}

//----- Tags ------------------------------------

// Tags：以@开头的标示
// 下面是常用的Tag

/**
 * 简单的描述
 *
 * 你可以任意扩展描述，成千上万行都可以
 *
 * 用 {\@link ellement} 指向一个 element
 * 比如：指向a1: {@link a1}
 * 
 * 用 {\@link url} 指向一个站点
 * 比如：{@link http://www.sina.com.cn 新浪网}
 * 
 * 用 {\@source} 显示源代码.
 * 比如：显示函数的代码：
 * {@source } 
 * 
 * 可用Tag列表:
 * type 是PHP类型：integer, array, mixed, string等
 *
 * - @abstract
 * - @access       public or private
 * - @author       作者 &lt;author@email>
 * - @copyright    版权
 * - @deprecated   废弃
 * - @deprec       deprecated的简写
 * - @example      指向例子
 * - @exception    兼容javadoc
 * - @global       type $globalvarname
 * - @global       type 函数中的全局变量描述
 * - @ignore
 * - @internal     给高级程序员看的内部细节描述
 * - @param        type [$varname] 描述
 * - @return       type 描述
 * - @link         URL
 * - @name         procpagealias [不懂]
 * - @name         $globalvaralias
 * - @magic        兼容phpdoc.de
 * - @package      包名
 * - @see          指向其他元素的名字，如函数名，类方法等
 * - @since        一个版本号或日期
 * - @static
 * - @staticvar    type 函数中的静态变量的描述
 * - @subpackage   子包
 * - @throws       兼容Javadoc
 * - @todo         待办列表，兼容phpdoc.de
 * - @var          type    类变量的类型
 * - @version      版本
 */
function if_there_is_an_inline_source_tag_this_must_be_a_function()
{
// ...
}


//----- 可以文档的源代码元素 ------------------------------------

//-- 包 

/*
 * Phpdoc划分包的逻辑：
 * 函数、常量、全局变量属于包
 * 方法、类变量属于类
 * 包可以包含多个类
 *
 * 一个文件中不要包含多个包
 */

//--- 程序文件级 --------------------
/*
 * 文件的第一个块就是 文件级的文档块(page-level Docblock)
 * 或者包含@package标签
 * 它可以有这些元素：
 *   标准标签
 *   @package
 *   @subpackage
 *
 */

//--- Include/Require 语句 ----------
/*
 * 它可以有这些元素：
 *   标准标签
 */ 

//--- define 语句 -------------------
/*
 * 它可以有这些元素：
 *   标准标签
 *   @name
 */ 

//--- function 声明 -------------------
/*
 * 它可以有这些元素：
 *   标准标签
 *   @global
 *   @param
 *   @return
 *   @staticvar
 *   inline {@source}
 */ 

//--- 全局变量 ------------------------
/*
 * 它可以有这些元素：
 *   标准标签
 *   @name
 */ 

//--- class 声明 -------------------
/*
 * 它可以有这些元素：
 *   标准标签
 *   @package
 *   @subpackage
 *   @static
 */ 

//--- class 变量 -------------------
/*
 * 它可以有这些元素：
 *   标准标签
 *   @var
 */ 

//--- class 变量 -------------------
/*
 * 它可以有这些元素：
 *   标准标签
 *   @global
 *   @param
 *   @return
 *   @static
 *   @staticvar
 *   inline {@source}
 */ 

/*
 * 标准文档标签
 * 常用的：
 *   @author
 *   @copyright
 *   @version
 *   @since
 *   @link
 *   @see
 * 其他：
 *   @tutorial
 *   @example
 *   @access
 *   @deprecated
 *   @ignore
 *   @internal
 *   inline {@internal}}
 *   inline {@inheritdoc}
 *   inline {@link}
 */

/*
 * 文档标签的继承关系
 *
 * Class子类可以继承父类的文档，几个简单的规则：
 *
 * @author, @version, @copyright 自动继承，除非显示指明
 * @package and @subpackage 也会继承，但是建议显示申明，以避免名字冲突
 * 如果没有简单描述，则会继承
 * 如果没有长简单描述，则会继承
 * 如果有长描述，想继承父类的描述，则使用inline标签 {@inheritdoc}
 */

//----- 命令行参数说明 ------------------------------------
// phpdoc -h 查看帮助, 参数如下：
//
/* -c --config 载入配置文件，如：-c defualt ;载入default.ini文件
 * -cp --converterparams 动态扩展转换器的参数，多个值用逗号分割
 * -ct --customtags 自定义tag，多个值用逗号分割；如：-ct mgtag,yourtag  => @mytag @yourtag
 * -d --directory 指定要解析的目录
 * -dc --defaultcategoryname 指定默认分类名，默认值为:defaul
 * -dh --hidden 相当于-dh on，让phpdoc解析以.开头的隐藏文件和目录
 * -dn --defaultpackagename 指定默认包名，默认是：default
 * -ed --examplesdir 例子文件寻找路径，如：-ed /full/path/to/example
 * -f --filename 要解析的源文件名，用,分割，可以使用 * ?
 * -i --ignore 不解析的文件名或目录，用,分割，可以使用 * ? ；
 *    - -i  忽略 /path/to/here/tests/* 和 /path/tests/*
 *    - -i *.inc 忽略所有的 .inc 文件 *
 *    - -i *path/to/* 忽略 /path/path/to/my/* 和 /path/to/*
 *    - -i *test* 忽略 /path/tests/* 和 /path/here/my_test.php
 * -is --ignoresymlinks 忽略任何链接文件，这个只在Linux/Unix下有效，因为Win下没有链接文件
 * -it --ignore-tags 忽略某些tag；通常用于创建不同版本的文档；如给普通用户的文档，就不需要@todo标签
 *    忽略inline标签，加上大括号，如--ignore-tags {@internal}
 *    参数是完整名字，如-it @todo，  -it todo 是错误的写法
 * -j --javadocdesc 使用javadoc兼容标签
 * -o --output 指定要使用的转换器和模板；默认可选：
 *   HTML:frames:* - 输出带框架的HTML页面
 *     HTML:frames:default - 类Javadoc模板，没有太多格式
 *     HTML:frames:earthli - Marco von Ballmoos写的模板，非常漂亮
 *     HTML:frames:l0l33t - 非常漂亮的模板
 *     HTML:frames:phpdoc.de - 类phpdoc.de's PHPDoc
 *     HTML:frames:phphtmllib - 非常好的用户发行模板
 *      以上模板都有javascript增强版本：HTML:frames:DOM/name 其中name表示 default, l0l33t, phpdoc.de, 等等
 *     HTML:frames:phpedit - 基于PHPEdit帮助生成器
 *
 *   HTML:Smarty:* - 输出不带框架的HTML
 *     HTML:Smarty:default - 用css控制页面布局的模板
 *     HTML:Smarty:HandS - Layout is based on PHP, but more refined, with logo image
 *     HTML:Smarty:PHP - Layout is identical to the PHP website
 *
 *   CHM:default:* - 输出成CHM格式，需要用Windows的Help软件编译
 *     CHM:default:default - 基于HTML:frames:l0l33t
 *
 *   PDF:default:* - 输出成PDF文档
 *     PDF:default:default - 标准格式
 *
 *   XML:DocBook:* - 输出成XML--DocBook格式
 *     XML:DocBook/peardoc2:default - pear.php.net（第2版）
 *
 * -p --pear Parse a PEAR-style repository (package is directory, _members are @access private) on/off default off 
 * -po --packageoutput output documentation only for selected packages. Use a comma-delimited list 
 * -pp --parseprivate 开启；默认不显示@access private的文档
 * -q --quiet 关闭多余信息；用法：-q on --不显示  -q off --显示，默认值
 * -ric --readmeinstallchangelog Specify custom filenames to parse like README, INSTALL or CHANGELOG files 
 * -s --sourcecode generate highlighted sourcecode for every parsed file (PHP 4.3.0+ only) on/off default off 
 * -t --target 要输出的路径
 * -ti --title 文档的标题
 * -tb --templatebase 指定自己的模板目录
 * -ue --undocumentedelements 为没有文档的元素 产生警告; 用法：-ue on  -ue off (默认值)
 */

/*
 * phpdoc -t /path/to/output -d path/to/directory1,/another/path,/third/path 
 *   -f /path/to/anotherfile.php -i *test.php,tests/ -pp on -ti My Title -o HTML:frames:phpedit
 *
 * phpdoc -c myconfig
 */

?>



</pre>
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/120007#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 04 Sep 2007 02:36:13 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/120007</link>
        <guid>http://sofire.javaeye.com/blog/120007</guid>
      </item>
      <item>
        <title>Dmd编译器学习笔记</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/112465" style="color:red;">http://sofire.javaeye.com/blog/112465</a>&nbsp;
          发表时间: 2007年08月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Dmd编译器学习笔记<br /><br />英文原文在这里：<br /><a href="http://digitalmars.com/d/dcompiler.html" target="_blank">http://digitalmars.com/d/dcompiler.html</a><br />在这里有一篇翻译文章：<br /><a href="http://sofire.javaeye.com/blog/111667" target="_blank">http://sofire.javaeye.com/blog/111667</a><br />不过，主要是关于windows的；我更关心Linux下的使用。<br />顺便看看两者有啥区别。<br /><br /><span style="font-size: 14pt"><strong>相关文件</strong></span><br />注意：<br /><span style="color: red"><br />Linux的dmd配置文件是dmd.conf<br />Windows的配置文件是sc.ini<br /></span><br /><br /><ul><li>/dmd/bin/dmd</li>    D 编译器的可执行文件<br /><li>/dmd/bin/dumpobj</li>    Elf file dumper <br /><li>/dmd/bin/obj2asm</li>    Elf文件反汇编器<br /><li>/dmd/bin/dmd.conf</li>    全局配置文件(复制到 /etc/dmd.conf) <br /><li>/dmd/lib/libphobos.a</li>    D运行库(复制到 /usr/lib/libphobos.a) <br /></ul>	<br /><br /><span style="font-size: 14pt"><strong>DMD的安装</strong></span><br /><ol><li>下载dmd程序：http://ftp.digitalmars.com/dmd.zip，解压到~/dmd目录</li><li>复制dmd.conf文件到/etc目录</li><pre name="code" class="java">
cp ~/dmd/bin/dmd.conf /etc
</pre><li>给下面的文件添加执行权限</li><pre name="code" class="java">
chmod u+x ~/dmd/bin/{dmd,dumpobj,obj2asm,rdmd}
</pre><li>把~/dmd/bin添加到PATH环境变量；或者把它们复制到/usr/local/bin目录下（不要只复制可执行程序）</li><li>复制库文件到/usr/lib目录</li><pre name="code" class="java">
cp ~/dmd/lib/libphobos.a /usr/lib
</pre><br /></ol><br /><br />以上安装过程比较简单，只有PATH环境变量设置正确了，就应该没有什么问题<br /><br /><span style="font-size: 14pt"><strong>编译参数和开关</strong></span><br />命令的格式：<br /><pre name="code" class="java">
dmd   files...  -switches... 
</pre><br />[Windows]支持以下类型的文件：<br /><pre name="code" class="java">
Extension      File Type  
none           D source files  
.d             D source files  
.di            D interface files  
.obj           Object files to link in  
.lib           Object code libraries to search  
.exe           Name output executable file  
.def           module definition file  
.res           resource file  
</pre><br />[Linux]支持以下类型的文件：<br /><pre name="code" class="java">
Extension      File Type
none  	       D source files
.d 	           D source files
.di 	       D interface files
.o 	           Object files to link in
.a 	           Library files to link in
</pre><br /><span style="color: red">好像不支持.so文件--这一点不肯定</span><br /><br /><span style="font-size: 12pt"><strong><span style="color: red">编译开关之一</span></strong></span><br /><pre name="code" class="java">
-debug
    编译调试代码

-debug=level
    编译调试代码：code &lt;= level

-debug=ident
    编译调试代码：标识符为ident

-version=level
    生成版本代码：>=level

-version=ident
    生成版本代码：==ident
    
-unittest
    编译单元测试代码（还有断言）

-cov
    添加覆盖率分析指令；运行程序后，会生成.lst文件

-release
    生成发行版本；会去掉契约和断言等信息
</pre><br /><br /><strong>-debug / -version</strong><br />debug、version的使用方法很相似<br /><pre name="code" class="java">
//debug.d
import std.stdio;

void main()
{
    debug    { writefln("debug"); }
    debug(1) { writefln("debug(1)"); }
    debug(2) { writefln("debug(2)"); }

    debug(ERROR) { writefln("debug(ERROR)"); }
    debug(WARN)  { writefln("debug(WARN)"); }

    version(HOME)      { writefln("version(HOME)"); }
    version(BUSINESS)  { writefln("version(BUSINESS)"); }

    version(WINDOWS) {} else { writefln("version(!WINDOWS)"); }
}
</pre><br />编译并运行之：<br /><pre name="code" class="java">
# dmd -debug -run debug.d
debug
debug(1)
version(!WINDOWS)

# dmd -debug=1 -run debug.d
debug
debug(1)
version(!WINDOWS)

# dmd -debug=2 -run debug.d
debug
debug(1)
debug(2)
version(!WINDOWS)

# dmd -debug=ERROR -run debug.d
debug(ERROR)
version(!WINDOWS)

# dmd -debug=WARN -run debug.d
debug(WARN)
version(!WINDOWS)

# dmd -version=HOME -run debug.d
version(HOME)
version(!WINDOWS)

# dmd -version=BUSINESS -version=WINDOWS -run debug.d
version(BUSINESS)
</pre><br /><br /><strong>-unittest</strong><br /><pre name="code" class="java">
//unittest.d
import std.stdio;

class A
{
    int i;
    this(int v) {
        i = v;
    }   

    unittest {
        A a = new A(1);
        assert(a.i == 1); 
        assert(a.i != 0); 
    }   
}

int add(int a, int b)
{
    return a - b;
    // 这里没有unittest
}

void main()
{
    // 这里没有unittest
}

unittest {
    assert(add(1, 2) == 3); 
}
</pre><br />先正常编译，没有语法错误：<br /><pre name="code" class="java">
# dmd -run unittest.d
</pre><br />再编译单元测试代码<br /><pre name="code" class="java">
# dmd -unittest -run unittest.d 
Error: AssertError Failure unittest(30)
</pre><br />30行有错误？add函数写错了：（<br /><br /><strong>-cov</strong><br />看看覆盖率分析选项：<br /><pre name="code" class="java">
//cov.d
import std.stdio;

void main()
{
    for (int i; i &lt; 2; i++)
    {
        if (i &lt; 5)
            writefln("i &lt; 5");
        else
            writefln("i >= 5");
    }
}
</pre><br />编译并运行：<br /><pre name="code" class="java">
# dmd -cov -run cov.d
i &lt; 5
i &lt; 5
</pre><br />得到覆盖率分析文件：cov.lst：（注意：编译完并不会有这个文件；运行程序后才会生成）<br /><pre name="code" class="java">
       |//cov.d
       |import std.stdio;
       |
       |void main()
       |{
      6|    for (int i; i &lt; 2; i++)
       |    {
      2|        if (i &lt; 5)
      2|            writefln("i &lt; 5");
       |        else
0000000|            writefln("i >= 5");
       |    }
       |}
cov.d is 75% covered
</pre><br />第6行运行了6次--自己算算是不是；<br />第11行运行了0次--搜索000000字符串，就能轻松找到没有覆盖到地方；<br />更多详情参考：<a href="http://digitalmars.com/d/code_coverage.html" target="_blank">http://digitalmars.com/d/code_coverage.html</a><br /><br /><strong> -release </strong><br />	用法很简单，不举例了<br /><br /><span style="font-size: 12pt"><strong><span style="color: red">编译开关之二</span></strong></span><br /><pre name="code" class="java">
-D
    生成文档

-Dddocdir
    把文档生成到docdir目录；注意是 -Dd
	
-Dffilename
	指定文档的文件名；
</pre><br />编译命令很简单：<br /><pre name="code" class="java">
dmd -D debug.d
</pre><br />关于文档的更多信息参考：<a href="http://sofire.javaeye.com/blog/111881" target="_blank">http://sofire.javaeye.com/blog/111881</a><br /><br /><span style="font-size: 12pt"><strong><span style="color: red">编译开关之三</span></strong></span><br /><pre name="code" class="java">
-H
    生成.di接口文件

-Hddir
    把接口文件生成到dir目录；注意是 -Hd

-Hffilename
    指定接口文件名；注意是 -Hf
</pre>	<br />关于接口，看一段翻译：<br />当处理源文件中的import声明时，编译器会搜索import对应的源文件，从中提取出需要的信息。<br />编译器同时也会搜索D接口文件，D接口文件中只包含模块中需要导入的内容，而不是整个模块。<br />使用D接口文件的好处是：<br />	<ul><br />	D接口文件更小，和D源文件相比处理起来更快。<br />	可以隐藏源代码。比如以接口文件和object库的方式提供源程序，而不是提供全部源代码。<br />	</ul><br />D接口文件可以在编译D源文件时用-H开关创建，D接口文件的后缀是.di。<br />当编译器分解import声明时，搜索寻找.di形式的D接口文件，再寻找D源文件。<br />D接口文件有点和C++头文件相似，但这不是必需的，它不属于D语言，只是编译器的一个功能，只是用来优化程序的构建。<br /><span style="color: red"><br />dmd -H生成的接口文件包括了源代码；只是去掉了注释，断言等信息；具体怎么回事，待弄明白了再来改这里(TODO)<br /></span><br /><br /><br /><span style="font-size: 12pt"><strong><span style="color: red">编译开关之四</span></strong></span><br /><pre name="code" class="java">
-c
    只编译，不链接；简单点说就是只生成.o文件，不生成可执行文件

-Ipath
	指定import路径；多个路径之间用分号(;)分割；允许有多个-I，并按照-I指定的路径顺序进行搜索

-Jpath
	指定D源程序中import表达式的搜索路径；多个路径之间用分号(;)分割；
	允许有多个-J，并按照-J指定的路径顺序进行搜索

-Llinkerflag
   	 把linkerflag传递给连接程序(linker)，比如: -L-L/usr/lib

-o-
    不生成.o文件，一般和-H、-D一起使用

-offilename
    指定输出文件名；可以是可执行程序，也可以是其他文件；注意是：-of

-odobjdir
    把.o文件生成到objdir目录；默认是生成到当前目录；注意是：-od

-op
	默认生成的object文件(.o)会在当前目录；添加-op参数则会生成到源文件所在目录
</pre><br /><br /><strong>-c</strong><br /><pre name="code" class="java">
	dmd debug.d     # 生成debug可执行文件
	dmd -c debug.d  # 生成debug.o文件
</pre><br />dmd编译器默认是编译成.o文件后，再和其他库连接成可执行文件；<br />某些情况下不需要编译成可执行文件，比如没有main函数--也编译不成<br />这时就可以只编译成.o文件<br /><br />bud等程序build工具，可以自动判断文件是否有main函数，并生成相应的文件；<br />但dmd编译器不是这样的；所以，熟悉了dmd编译器后，可以只使用bud等工具来编译程序<br /><br /><strong>-I / -J</strong><br /><pre name="code" class="java">
import std.stdio;				// -I
void main()
{
    auto b = import("x.d");		// -J
}
</pre><br /><br />自己体会它们的用途吧：）<br />注意：如果在搜索路径下有同名文件的话，可能出现奇怪的问题；避免出现这种情况，或者改变参数的顺序<br /><br /><strong> -Llinkerflag </strong><br />一般是-L-L 和 -L-l参数，指定lib路径和库文件<br />比如：-L-L/usr/local/lib  -L-lsqlite3<br />对linker不熟悉，回头在详细写这块<br /><br /><strong>-o-</strong><br />如果只想生成文档，连.o文件都不想要；则-o- 就是你想要的了<br /><br /><strong>-offilename</strong><br />默认情况下，是根据源文件名来确定后续文件的文件名；<br />比如foo.d 会生成 <em>foo.o</em> 与 <em>foo</em> 文件；<br />通过-of参数可以改变输出文件的名字：<br />dmd -ofbar.exe foo.d<br /><br />它不会自动添加后缀：<br />dmd -c -ofbar foo.d<br />生成文件是 <em>bar</em>，而不是<em>bar.o</em>，这可能不是你想要的<br /><br /><strong>-odobjdir -op</strong><br />.o文件默认生成在当前目录下；<br />-od 是指定生成目录，-od.和默认相同<br />-op 是把.o生成到源文件所在目录<br />具体生成到什么目录下，就看自己的爱好了；<br />喜欢干净，就用-od吧；对了，-run参数能生成更干净的代码；）<br /><br /><span style="font-size: 12pt"><strong><span style="color: red">编译开关之五</span></strong></span><br /><pre name="code" class="java">
-O
    优化生成的代码，使程序运行得更快

-g
    添加调试信息

-gc
    添加C风格的调试信息（为旧的gdb）

-inline
    用内联函数的方式进行优化；相当于C的inline

-fPIC
    生成位置无关代码

-d
    允许废弃的特征

-profile
    profile the runtime performance of the generated code 
	参见：http://www.digitalmars.com/ctg/trace.html
</pre><br /><br />这几个参数，要么很简单，要么不懂含义；也懒得去研究具体的意思了。<br />其中的-g参数涉及到使用调试器；我喜欢用writefln调试；唉，回头再研究吧。<br /><br /><br /><span style="font-size: 12pt"><strong><span style="color: red">编译开关之六</span></strong></span><br /><pre name="code" class="java">
--help
    打印帮助

-quiet
   	安静模式，不输出无关紧要的信息

-v
    显示编译细节

-w
	显示编译警告
</pre><br /><br /><span style="font-size: 12pt"><strong><span style="color: red">编译开关之七</span></strong></span><br /><pre name="code" class="java">
-run srcfile args...
    编译，链接，然后运行程序srcfile；args...(到命令行结束)都是程序的参数；
	它不会保留.o和可执行程序（No .o or executable file is left behind）
</pre><br /><br />文章开始就有怎么使用的例子<br />需要注意的是参数的顺序，因为很多写法都是错误的，正确的是：<br /><pre name="code" class="java">
dmd 相关文件 编译开关 -run 含main的源文件 程序参数1 程序参数2
</pre><br />各种参数放在-run前面，然后是含有main的源程序，再后面的内容会全部传递给运行程序，作为参数<br /><br /><span style="font-size: 14pt"><strong>链接Linking</strong></span><br />在dmd编译成功后，它会再调用连接程序；用-c参数可以不进行连接<br />连接的实际处理程序其实是gcc；这样能保证和gcc编译的模块兼容<br /><br /><br /><span style="font-size: 14pt"><strong>环境变量</strong></span><br /><strong>CC</strong><br />默认是用gcc进行连接，可以通过设置CC环境变量，使用其他连接器<br /><br /><strong> DFLAGS </strong><br />The value of DFLAGS is treated as if it were appended to the command line to dmd. <br />没有弄明白它是怎么回事；（<br /><br /><span style="font-size: 14pt"><strong>dmd.conf初始化文件</strong></span><br />dmd会按照下面的目录顺序查找<br /><ol><li>当前工作目录</li><li>环境变量HOME指定的目录</li><li>dmd命令所在目录，即bin目录</li><li>/etc目录</li></ol><br /><br />dmd.conf的内容看起来像这样：<br /><pre name="code" class="java">
; dmd.conf 是dmd的配置文件
; 分号是注释符号
; %%包含的名字会用相应的环境变量替换
; %@P%会被本文件的路径替换，即dmd.conf文件所在路径
[Environment]
DFLAGS="-I%@P%/../src/phobos"
DDOCFILE=candydoc/proj.ddoc
</pre><br /><br />格式是 NAME=value；NAME即使是小写，也会被处理成大写；<br />里面的DFLAGS的值会覆盖环境变量指定的值<br /><br /><span style="font-size: 14pt"><strong>和Windows版本的区别</strong></span><br /><ul><li> 字符串文章量是只读的；对它写会导致段错误</li><span style="color: red"><li> 配置文件是dmd.conf，而不是sc.ini</span></li><li> Windows有一个@cmdfile开关</li><li> Windows有一个-nofloat开关</li><li> 环境变量上有些不一样</li></ul><br /><br />总结：<br />和gcc比起来，参数少多了 ;)<br />虽然可以用bud进行编译，但理解dmd还是必要的。<br />反正也不复杂，花点时间学习一下还算值得。
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/112465#comments" style="color:red;">已有 <strong>2</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 15 Aug 2007 17:28:00 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/112465</link>
        <guid>http://sofire.javaeye.com/blog/112465</guid>
      </item>
      <item>
        <title>Ddoc文档注释学习笔记</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/111881" style="color:red;">http://sofire.javaeye.com/blog/111881</a>&nbsp;
          发表时间: 2007年08月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Ddoc学习笔记<br /><br />ddoc的英文文档在：<br />http://www.digitalmars.com/d/ddoc.html<br /><br />D语言可以在代码中嵌入文档注释（以下称文档）。<br />它不仅仅是注释，而且还是一段可供阅读的文档。<br />这样做的好处是，在开发、维护代码的时候，就能同时维护文档。<br />对于程序员，写文档比写代码还痛苦；写注释倒是一个大家还可以接受的事情。<br />在写代码的时候，顺便把文档写了，也许能改善一下文档不全的问题。<br />个人挺喜欢这样方式的。至于太团队项目开发中有没有效果。<br />因为还没有实践过，不敢乱做评判。<br /><br /><br />文档有以下几个步骤处理:<br /><ol><li>词法 文档注释被 附加的记号 标识..</li><li>解析 文档注释 被关联到 特殊的定义和组合</li><li>段落 每个文档注释 被 分解到一个段落的序列</li><li>处理特定的节.</li><li>非特殊的段落完成后高亮显示.</li><li>合并模块中的所有段落.</li><li>在最终结果执行宏文本替换.</li></ol><br /><br />下面按照这个顺序来展开；<br /><br />推荐先熟悉文档的写法，一般编译方法，常用节；和学习使用Candydoc；<br />其他内容可以后期在看；<br /><br /><br /><strong><span style="font-size: 14pt">文档的语法</span></strong><br /><br />从一个最简单的程序开始吧：<br /><br /><pre name="code" class="java">
/**
 * 这个一个Ddoc文档例子
 * 
 * Authors: Dehong Liu
 * Date:    2007年8月13日
 */

void main()
{
}
</pre><br />注意注释符号 /**，和单词Authors/Date。<br /><br />编译这个文件(a1.d)，并且生成文档doc1/a1.html<br /><pre name="code" class="java">
dmd -Dddoc1 a1.d			# -DdXXX 指定文档生成路径为XXX
</pre><br />用浏览器打开这个html文件，看起来像下面这样【见附件 doc1/a1.html】：<br /><pre name="code" class="java">
a1

void main();
    这个一个Ddoc文档例子

    Authors:
    Dehong Liu

    Date:
    2007年8月13日 

-------------------------------------------------------------	
Page generated by Ddoc. 
</pre><br />看着很奇怪？这只是个开始。至少明白了哪些写法会变成文档，表现形式和怎么生成。<br /><br />现在一个个开始解释。<br />文档有下面三种写法：<br /><pre name="code" class="java"> 
 /** ...   */       	/ 后面两个*	
 /++ ...   +/       	/ 后面两个+
 ///					三个 /	
</pre><br /><br />下面有一个完整的文档写法例子（a2.d）：<br /><pre name="code" class="java">
/// 这是一个行文档注释

/** 这也是 */

/++ 同样 +/

/**
   这是一个摘要文档
 */

/**
 * 开头的* 不是文档的一部分
 */

/*********************************
   在 /** 后面的连续的*，
   不是文档的一部分
 */

/++
   这也是一个摘要文档
 +/

/++
 + 开头的+ 不是文档的一部分
 +/

/+++++++++++++++++++++++++++++++++
   在 ／++ 后面的连续的+，
   不是文档的一部分
   上面的斜杠是中文符号，避免语法错误

   换行：注意上面的空行
 +/

/*********** 前面连续的*号不是，这部分*****是文档，后面的又不是  *****************/

module a2;

</pre><br /><br />输出的html结果【见附件 doc1/a2.html】：<br /><pre name="code" class="java">
a2
这是一个行文档注释

这也是

同样



这是一个摘要文档



开头的* 不是文档的一部分



在 /** 后面的连续的*， 不是文档的一部分



这也是一个摘要文档



开头的+ 不是文档的一部分



在 ／++ 后面的连续的+， 不是文档的一部分 上面的斜杠是中文符号，避免语法错误

换行：注意上面的空行

前面连续的*号不是，这部分*****是文档，后面的又不是 
</pre><br /><br /><br /><strong><span style="font-size: 14pt">文档和申明关联</span></strong><br /><br />每一个文档都和一个申明(declaration)相关联：<br /><div class="quote_title">引用</div><div class="quote_div"><br />1. 如果某单行文档的最左边是空格，它就和下面的申明关联<br />2. 多个关联到同一个申明的文档会被连接在一起<br />3. 没有关联到申明的文档会被忽略<br />4. 在module申明前的所有文档会被应用到整个模块<br />5. 如果文档出现在申明的右边，则关联到它<br />6. 如果文档只是ditto，则应用上一个申明的文档<br />7. 如果一个申明没有文档，则不会出现在html输出中，要出现，可以写一个空的文档，如 ///<br /></div><br /><br />看一个例子吧：<br /><pre name="code" class="java">
/**
 * 整个模块的文档
 */

module a3;

int a;  /// a;的文档，b没有文档
int b;

/** c和d的文档 */
/** 再添加些c和d的文档的文档 */
int c;
/** ditto */
int d;

/** e和f的文档 */ int e;
int f;	/// ditto

/** g的文档 */
int g; /// 在添加点g的文档

/// C和D的文档
class C
{
    int x;    /// C.x的文档

    /** C.y 和 C.z的文档 */
    int y;
    int z;    /// ditto
}

/// ditto
class D
{
}

int h; // 只有注释，没有文档，不会出现在html中

// 下面是空文档
int j; /// 

/// 被忽略的文档
</pre><br /><br />看起来像这样【见附件 doc1/a3.html】<br /><pre name="code" class="java">
a3
整个模块的文档

int a;
    a;的文档，b没有文档

int c;
int d;
    c和d的文档

    再添加些c和d的文档的文档

int e;
int f;
    e和f的文档

int g;
    g的文档

    在添加点g的文档

class C;
class D;
    C和D的文档

    int x;
        C.x的文档

    int y;
    int z;
        C.y 和 C.z的文档

int j;
</pre><br /><br /><br /><strong><span style="font-size: 14pt">文档的节</span></strong><br /><br />a1.d例子中的Authors / Date 就是节(Sections)。<br />节由 "非空格字符" + ":" 组成，其中标识符部分叫节名，它不区分大小写<br /><br /><strong>概要(Summary)：</strong><br />	第一个节就是概要，它没有节名；<br />	它是第一个段落，遇到空行或者节名结束；<br />	可以把概要写成多行,但写成一行比较好<br />	概要节是可选的<br /><br /><strong>描述(Description)：</strong><br />	第二个没有名字的节 是描述<br />	遇到一个节名或者到文档的结束<br /><br />给个例子(a4.d)：<br /><pre name="code" class="java">
/***********************************
 * 这是一个概要(Brief summary)
 * 描述myfunch函数的使用；这两行形成一个概要节
 *
 * 描述节的第一个段落
 *
 * 还是描述节：
 * 可以写更多内容
 */

void myfunc() { }
</pre><br />html输出【见附件 doc1/a4.html】：<br /><pre name="code" class="java">
void myfunc();
    这是一个概要(Brief summary) 描述myfunch函数的使用；这两行形成一个概要节

    描述节的第一个段落

    还是描述节： 可以写更多内容 
</pre><br /><br /><br /><strong><span style="font-size: 14pt">标准节</span></strong> <br /><br />有一些预定义好了的节，看看它们的意思：<br /><ul><li><strong>Authors:</strong> 		列出作者名字</li><li><strong>Bugs:</strong> 			列出已知BUG</li><li><strong>Date:</strong> 			列出当前修订的时间，应当是 std.date 能解析的形式</li><li><strong>Deprecated:</strong> 		做 "抗议"标记(？弃用标记)--最好给出理由和纠正的方法</li><li><strong>Examples:</strong> 		例子</li><li><strong>History:</strong> 		修订历史</li><li><strong>License:</strong> 		版权申明</li><li><strong>Returns:</strong> 		解释函数的返回值；如果返回void，就不要写在文档中了</li><li><strong>See_Also:</strong> 		列出相关符号，或者URL链接</li><li><strong>Standards:</strong> 		如果申明涉及到某个标准，在此描述</li><li><strong>Throws:</strong> 			列出在哪些环境下会抛出异常</li><li><strong>Version:</strong> 		指定当前申明的版本号</li><li><strong>See_Also:</strong> 		列出相关符号，或者链接</li><li><strong>See_Also:</strong> 		列出相关符号，或者链接</li></ul><br /><br />特殊节：一些有特殊含义和语法的节<br /><ul><li><strong>Copyright:</strong> 		版权申明。如果是在module申明中，该节会被COPYRIGHT宏替换；</li><li><strong>Params:</strong> 			函数的参数描述文档； </li>							"标识符 =' 开始一个新的参数描述；它可以跨越多行<li><strong>Macros:</strong> 			和Params节有类似的语法；它是一系列 NAME=value 组成</li>							NAME 是宏名，VALUE是要替换成的文字<br /></ul><br /><br />全部列出来看看：<br /><pre name="code" class="java">
/** Copyright: Public Domain */

module a5;

/**
 * Authors: Melvin D. Nerd, melvin@mailinator.com
 *
 * Bugs: Doesn't work for negative values.
 *
 * Date: March 14, 2003
 */

void foo1() {}

/**
 * Deprecated: superseded by function bar().
 */

deprecated void foo2() {  }

/**
 * Examples:
 * --------------------
 * writefln("3"); // writes '3' to stdout
 * --------------------
 *
 * History:
 *  V1 is initial version
 *
 *  V2 added feature X
 *
 * License: use freely for any purpose
 */

void bar() { }

/**
 * Read the file.
 * Returns: The contents of the file.
 */

void[] readFile(char[] filename) { return "filename"; }

/**
 * See_Also:
 *    foo, bar, http://www.digitalmars.com/d/phobos/index.html
 *
 * Standards: Conforms to DSPEC-1234
 *
 * Throws: WriteException on failure.
 *
 * Version: 1.6a
 */

void writeFile(char[] filename) {  }

// 特殊节

/***********************************
 * foo does this.
 * Params:
 *  x = is for this
 *      and not for that
 *  y = is for that
 */

void foo(int x, int y)
{
}

/**
 * Macros:
 *  FOO =   now is the time for
 *      all good men
 *  BAR =   bar
 *  MAGENTA =   &lt;font color=magenta>&lt;/font>
 *  COPYRIGHT = 版权归热爱地球的火星人所有
 */

/**
 * Foo: $(FOO)
 * Bar: $(BAR)
 * MAGENTA: $(MAGENTA)
 * Copyright: Public Domain 
 */
void foo3() {   }

</pre><br />输出效果是【见附件doc1/a5.html】：<br /><pre name="code" class="java">
a5

void foo1();
    Authors:
    Melvin D. Nerd, melvin@mailinator.com

    BUGS:
    Doesn't work for negative values.

    Date:
    March 14, 2003

deprecated void foo2();
    Deprecated:
    superseded by function bar().

void bar();
    Examples:

     writefln("3"); // writes '3' to stdout



    History:
    V1 is initial version

    V2 added feature X

    License:
    use freely for any purpose

void[] readFile(char[] filename);
    Read the file.

    Returns:
    The contents of the file.

void writeFile(char[] filename);
    See Also:
    foo, bar, http://www.digitalmars.com/d/phobos/index.html

    Standards:
    Conforms to DSPEC-1234

    Throws:
    WriteException on failure.

    Version:
    1.6a

void foo(int x, int y);
    foo does this.

    Params:
    int x 	is for this and not for that
    int y 	is for that

void foo3();
    Foo:
    now is the time for all good men

    Bar:
    bar

    MAGENTA:
    &lt;font color=magenta>&lt;/font>

    Copyright:
    Public Domain

Page generated by Ddoc. 版权归热爱地球的火星人所有 
</pre><br /><br />上面的例子都还好理解，把不容易理解的说说：<br />/** Copyright: Public Domain */ 在module申明前和后的效果不一样；<br />前者的效果在哪里？看页面的最后一行<br /><br />代码的文档是这么写的：<br /><pre name="code" class="java">
* Examples:  
* --------------------  
* writefln("3"); // writes '3' to stdout  
* --------------------  
</pre><br />代码的上下有一条分割线：至少三个连字符(-) <br /><br /><strong><span style="font-size: 14pt">文档的高亮处理</span></strong><br /><br /><strong>内嵌注释 Embedded Comments</strong><br />	不懂<br /><br /><strong>内嵌代码 Embedded Code</strong><br />	上面已经演示了<br /><br /><strong>内嵌的HTML Embedded HTML</strong><br />	内嵌的HTML代码不会被转译，直接输出给html文件<br />	虽然如此，基于某些原因（我没看懂），还是最好不要用html<br /><pre name="code" class="java">
/** Example of embedded HTML:
 *   
 *      &lt;li> &lt;a href="http://www.digitalmars.com">Digital Mars&lt;/a> &lt;/li>
 *      &lt;li> &lt;a href="http://www.classicempire.com">Empire&lt;/a> &lt;/li>
 */
</pre><br /><br /><strong>强调 Emphasis</strong><br />	函数参数等标识符会被以斜体，粗体，超链接等形式强调处理；具体形式文档没有说<br /><br /><strong>特殊符号Character Entities</strong><br />	&lt; > & 有特殊含义，如果要使用这3个符号，换成相应的：&lt; &gt; &amp;<br />	以下情况除外：在代码节中；不是立即跟一个 # 或 字母<br /><br /><strong><span style="font-size: 14pt">文档的宏</span></strong><br /><br />宏来自于下面这些地方，并按照特定步骤处理：<br /><ol><li>预定义宏</li><li>sc.ini配置文件中的DDOCFILE项指定的文件</li><li>命令行指定的*.ddoc文件</li><li>Ddoc运行时产生的定义，如BODY,TITLE</li><li>文件中的宏节</li></ol><br /><br />宏主要用在对文档格式的自定义上。<br />通过修改宏，能自定义HTML输出格式。<br /><br /><strong><span style="font-size: 14pt">CandyDoc的使用</span></strong><br /><br />dmd默认的格式很简单，可以使用CandyDoc来美化文档格式和增强功能。<br />使用方法很简单：(.ddoc是宏文件的后缀)<br />下载CandyDoc程序<br />	主页：http://www.dsource.org/projects/helix/wiki/CandyDoc<br />	下载：http://svn.dsource.org/projects/helix/downloads/candydoc-0.80.zip<br /><br />假设要编译: a5.d  doc2/candydoc<br /><pre name="code" class="java">
dmd -c -Dddoc2 a5.d doc2/candydoc/*.ddoc
</pre><br />生成的a5.html文件在 doc2/目录下，和candydoc一个目录，如果不是同一目录，会显示不正常；<br /><br />candydoc有2个.ddoc文件：candy.ddoc  modules.ddoc<br />如果要定义样式，在candy.ddoc中定义，一般不改；<br />modules.ddoc 要修改成自己的模块，默认是：<br /><pre name="code" class="java">
MODULES = 
    $(MODULE helix.basic)
    $(MODULE helix.color)
    $(MODULE helix.config)
    $(MODULE helix.linalgebra)
</pre><br /><br />以上面的5个程序为例：<br /><pre name="code" class="java">
MODULES =
    $(MODULE a.a1)
    $(MODULE a.a2)
    $(MODULE a.a3)
    $(MODULE a.a4)
    $(MODULE a.a5)
</pre><br />编译之：<br /><pre name="code" class="java">
dmd -c -Dddoc2 a1 a2 a3 a4 a5.d doc2/candydoc/*.ddoc
</pre><br /><br />如果要用Candydoc替换默认的文档格式，这么做：<br />修改dmd.conf文件，添加一行：<br />DDOCFILE=candy.ddoc<br />看起来像这样<br /><pre name="code" class="java">
[Environment]
DFLAGS=-I%@P%/../src/phobos -L-L%@P%/../lib -L-L/usr/lib -L-L/usr/local/lib -version=Phobos
DDOCFILE=candy.ddoc
</pre><br /><br />上面的配置只写了candy.ddoc文件，没有写module.ddoc。所以编译的时候要添加module.ddoc，这样做很不爽；<br />我的办法是自己写一个.ddoc文件--proj.ddoc<br />把candydoc.ddoc和 module.ddoc两个文件合并在一起<br /><br />[模块部分的导航要求所有的html都在一个目录下，这点还没有仔细研究，回头再写]<br /><br />注意，如果没有效果，检查：<br />1. Linux是修改dmd.conf文件；Windows是修改sc.ini文件；不要弄错了<br />2. dmd.conf 可能在多个地方：/etc 或 dmd命令所在目录等<br />3. candy.doc是相对于当前目录而已，不是dmd.conf文件；请按照实际情况设定路径<br /><br /><br />文档用起来还算简单，开始会不习惯，慢慢就习惯了。
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/111881#comments" style="color:red;">已有 <strong>6</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 14 Aug 2007 02:49:00 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/111881</link>
        <guid>http://sofire.javaeye.com/blog/111881</guid>
      </item>
      <item>
        <title>[zt]D语言编译器下载安装和编译参数</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/111667" style="color:red;">http://sofire.javaeye.com/blog/111667</a>&nbsp;
          发表时间: 2007年08月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font face="Arial">Javaeye的html编辑器用起来不爽。<br />
不知道怎么用UBB标签的表格标签。</font></p>
<p><font face="Arial">by: D语言论坛 http://bbs.yidabu.com/forum-10-1.html<br />
from: http://digitalmars.com/d/dcompiler.html<br />
version: 基于D 1.014</font></p>
<h5>D语言编译器下载</h5>
<p><font face="Arial">最新版DMD编译器下载(Win32,Linux)<br />
<a href="http://ftp.digitalmars.com/dmd.zip" target="_blank">http://ftp.digitalmars.com/dmd.zip</a></font></p>
<p><font face="Arial">最新版DMC下载(Win32，包含链接器和工具)<br />
<a href="http://ftp.digitalmars.com/dmc.zip" target="_blank">http://ftp.digitalmars.com/dmc.zip</a></font></p>
<p><font face="Arial">任意版本DMD下载:<br />
<a href="http://digitalmars.com/d/changelog.html" target="_blank">http://digitalmars.com/d/changelog.html</a></font></p>
<p><font face="Arial">Win32和Linux通用的文件说明：<br />
\dmd\src\phobos\<br />
运行时标准库源文件</font></p>
<p><font face="Arial">\dmd\src\dmd\<br />
DMD编译器前端源文件</font></p>
<p><font face="Arial">\dmd\html\d\<br />
文档</font></p>
<p><font face="Arial">\dmd\samples\d\<br />
示例程序</font></p>
<h5>Win32 D语言编译器</h5>
<p><font face="Arial">1 安装需求<br />
1.1 32位Windows(Win32)操作系统,比如Windows XP</font></p>
<p><font face="Arial">1.2 下载D语言编译器DMD.zip<br />
&nbsp;<a href="http://ftp.digitalmars.com/dmd.zip">http://ftp.digitalmars.com/dmd.zip</a></font></p>
<p><font face="Arial">1.3 下载链接器和工具DMC.zip<br />
&nbsp;http://ftp.digitalmars.com/dmc.zip</font></p>
<p><font face="Arial">2 主要文件</font></p>
<p><font face="Arial">\dmd\bin\dmd.exe<br />
D语言编译器可执行文件</font></p>
<p><font face="Arial">\dmd\bin\shell.exe<br />
简单的命令行shell</font></p>
<p><font face="Arial">\dmd\bin\sc.ini<br />
D语言编译器全局设置</font></p>
<p><font face="Arial">\dmd\lib\phobos.lib<br />
D运行时库文件</font></p>
<p><font face="Arial">3 安装指南</font></p>
<p><font face="Arial">打开控制台窗口（Windows XP只要点击[开始][命令提示符])。<br />
所有工具都是命令行工具，也就是说只能在控制台窗口里运行。<br />
切换到你安装D的根目录，解压下载下来的文件，dmd.zip会创建\dmd目录，dmc.zip会创建\dm目录。<br />
操作过程可能是这样：</font><font face="Arial"></font><font face="Arial">更详细的安装指南可以参考D语言论坛 http://bbs.yidabu.com/forum-10-1.html<br />
<a href="http://bbs.yidabu.com/thread-456-1.html" target="_blank">http://bbs.yidabu.com/thread-456-1.html</a></font></p>
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span>D:\d&gt;cd&nbsp;\ &nbsp;&nbsp;</span></span> </li>
    <li class=""><span>D:\d&gt;unzip&nbsp;dmd.zip &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>D:\d&gt;unzip&nbsp;dmc.zip&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p>&nbsp;<font face="Arial">4 编译示例<br />
</font><font face="Arial">\dmd\samples\d目录下有许多示例程序，进入目录<br />
命令行执行：</font><font face="Arial">&nbsp;</font></p>
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span>\dmd\bin\shell&nbsp;all.sh&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<p>可以编译示例程序。<br />
更详细的图文教程见这里：<br />
<a href="http://bbs.yidabu.com/thread-457-1.html" target="_blank">http://bbs.yidabu.com/thread-457-1.html</a></p>
<p><font face="Arial">5 编译器参数和开关节</font></p>
<p><font face="Arial">基本的命令格式如下：</font><font face="Arial">files可以是：&nbsp;</font></p>
<div class="dp-highlighter" style="WIDTH: 99%; HEIGHT: 62px">
<ol class="dp-j">
    <li class="alt"><span><span>dmd&nbsp;files...&nbsp;-switches...&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<p>
<table cellspacing="1" border="1" summary="" width="365" cellpadding="1" style="WIDTH: 365px; HEIGHT: 63px">
    <tbody>
        <tr>
            <td><strong>Extension </strong></td>
            <td><strong>File Type</strong></td>
        </tr>
        <tr>
            <td><em><strong>none</strong></em></td>
            <td>D source files</td>
        </tr>
        <tr>
            <td><strong>.d</strong>&nbsp;</td>
            <td>D source files</td>
        </tr>
        <tr>
            <td><strong>.di</strong> </td>
            <td>D interface files</td>
        </tr>
        <tr>
            <td><strong>.obj</strong> </td>
            <td>Object files to link in</td>
        </tr>
        <tr>
            <td><strong>.lib</strong> </td>
            <td>Object code libraries to search</td>
        </tr>
        <tr>
            <td><strong>.exe</strong></td>
            <td>Name output executable file</td>
        </tr>
        <tr>
            <td><strong>&nbsp;.def</strong> </td>
            <td>module definition file</td>
        </tr>
        <tr>
            <td><strong>&nbsp;.res</strong></td>
            <td>resource file</td>
        </tr>
    </tbody>
</table>
</p>
<p><font face="Arial">@cmdfile<br />
从文本文件中读入编译器参数和开关</font></p>
<p><font face="Arial">-c<br />
只编译不链接.</font></p>
<p><font face="Arial">-cov<br />
代码覆盖率分析指令</font></p>
<p><font face="Arial">-D<br />
从源文件中产生文档</font></p>
<p><font face="Arial">-Dddocdir<br />
把文档写到docdir目录</font></p>
<p><font face="Arial">-Dffilename<br />
把文档写到filename</font></p>
<p><font face="Arial">-d<br />
allow deprecated features</font></p>
<p><font face="Arial">-debug<br />
编译进调用代码</font></p>
<p><font face="Arial">-debug=level<br />
编译进&lt;= level 的调试代码</font></p>
<p><font face="Arial">-debug=ident<br />
compile in debug code identified by ident</font></p>
<p><font face="Arial">-g<br />
add CodeView 4 symbolic debug info</font></p>
<p><font face="Arial">-gc<br />
add CodeView 4 symbolic debug info in C format (for C debuggers)</font></p>
<p><font face="Arial">-H<br />
生成D接口文件</font></p>
<p><font face="Arial">-Hddir<br />
把D接口文件写到dir目录</font></p>
<p><font face="Arial">-Hffilename<br />
把D接口文件写到filename</font></p>
<p><font face="Arial">--help<br />
在控制台输出帮助</font></p>
<p><font face="Arial">-inline<br />
inline expand functions</font></p>
<p><font face="Arial">-Ipath<br />
import路径。可以用;分隔。可以有多个-I。照给定路径顺序搜索。</font></p>
<p><font face="Arial">-Jpath<br />
Import表达式导入文件的搜索路径，其他同-Ipath<br />
示例如：<br />
有一个test.d主要代码如下 ：<br />
<br />
</font></p>
<p><font face="Arial">假设temp.html的绝对路径是：D:\temp.html<br />
进入test.d所在目录，在控制台窗口执行：<br />
[Copy to clipboard] [ - ]<br />
CODE:<br />
dmd test.d -JD:\</font></p>
<p><font face="Arial">-Llinkerflag<br />
pass linkerflag to the linker, for example, /ma/li</font></p>
<p><font face="Arial">-nofloat<br />
Prevents emission of __fltused reference in object files, even if floating point code is present. Useful for library code. Windows only.( 本文出处: http://bbs.yidabu.com/forum-10-1.html )</font></p>
<p><font face="Arial">-O<br />
优化生成代码</font></p>
<p><font face="Arial">-o-<br />
不生成object文件。一般和-D,-H开关同时使用。<br />
Suppress generation of object file. Useful in conjuction with -D or -H flags.</font></p>
<p><font face="Arial">-odobjdir<br />
write object files relative to directory objdir instead of to the current directory<br />
把object文件写到当前目录的相对目录里。<br />
比如下面命令生成object\test.obj和test.exe,test.map<br />
<br />
dmd test.d -odobject</font></p>
<p><font face="Arial">-offilename<br />
设置输出文件名<br />
比如:<br />
[Copy to clipboard] [ - ]<br />
CODE:<br />
dmdtest.d -ofmy</font></p>
<p><font face="Arial">会输出my.exe( 本文出处: http://bbs.yidabu.com/forum-10-1.html )</font></p>
<p><font face="Arial">-op<br />
normally the path for .d source files is stripped off when generating an object file name. -op will leave it on.<br />
-profile<br />
profile the runtime performance of the generated code</font></p>
<p><font face="Arial">-quiet<br />
关闭不必要的编译器消息</font></p>
<p><font face="Arial">-release<br />
编译发行版，也就是不生成契约和断言代码</font></p>
<p><font face="Arial">-run srcfile args...<br />
compile, link, and run the program srcfile with the rest of the command line, args..., as the arguments to the program. No .obj or .exe file is left behind.</font></p>
<p><font face="Arial">-unittest<br />
编译进单元测试代码(还有断言)<br />
compile in unittest code, also turns on asserts( 本文出处: http://bbs.yidabu.com/forum-10-1.html )</font></p>
<p><font face="Arial">-v<br />
verbose</font></p>
<p><font face="Arial">-version=level<br />
compile in version code &gt;= level</font></p>
<p><font face="Arial">-version=ident<br />
compile in version code identified by ident</font></p>
<p><font face="Arial">-w<br />
enable warnings</font></p>
<h5>5 Linking链接</h5>
<p><font face="Arial">dmd编译器编译成功后会直接执行链接操作，不要链接就加上-c编译开关。</font></p>
<p><font face="Arial">编译程序时必须链接D运行时库phobos.lib和C运行时库snn.lib，如果LIB环境变量设置正确，这些操作都会自动进行的。<br />
一般这样设置：<br />
QUOTE:<br />
set LIB=\dmd\lib;\dm\lib</font></p>
<h5>6 Environment Variables环境变量</h5>
<p><font face="Arial">D程序编译器dmd使用下面的环境变量：<br />
<strong>1.1 DFLAGS</strong></font></p>
<p><font face="Arial">这里的值相当于dmd.exe的命令行参数<br />
D语言论坛 http://bbs.yidabu.com/forum-10-1.html 举个简单的例子：<br />
可以把自己写的或收集的模块放在\dmd\src\my\目录下，然后设置<br />
QUOTE:<br />
DFLAGS=&quot;-I%@P%\..\src\phobos;%@P%\..\src\my&quot;</font></p>
<p><font face="Arial">这样以后用到my下的模块时编译就省去写-I参数了<br />
<br />
<strong>1.2 LIB</strong></font></p>
<p><font face="Arial">链接器搜索库文件的路径。<br />
一般是这样的：( 本文出处: http://bbs.yidabu.com/forum-10-1.html )<br />
QUOTE:<br />
set LIB=\dmd\lib;\dm\lib<br />
<br />
<strong>1.3 LINKCMD</strong></font></p>
<p><font face="Arial">dmd所启动的链接器的路径，你也可以指定为另外的链接器来代替：<br />
QUOTE:<br />
set LINKCMD=\dm\bin\link<br />
<br />
<strong>1.4 PATH</strong></font></p>
<p><font face="Arial">如果dmd.exe找不到链接器，就会搜索PATH。注意：别的link.exe可能导致出错，确保在PATH搜索中首先找到Digtal Mars的link.exe，或者用LINKCMD指定链接器路径。<br />
按：PATH设置图文教程见：<a href="http://bbs.yidabu.com/thread-457-1.html">http://bbs.yidabu.com/thread-457-1.html</a></font></p>
<h5>7 sc.ini Initialization File</h5>
<p><font face="Arial">dmd会按照下面的目录顺序查找初始化文件sc.ini<br />
QUOTE:<br />
当前工作目录<br />
HOME环境变量指定目录<br />
dmd.exe所在目录</font></p>
<p><font face="Arial">如果找到sc.ine，会覆盖掉任何已有设置。这样可以方便地为不同程序设置不同的环境变量。</font></p>
<p><font face="Arial">环境变量在[Environment] 下面,形式是NAME=value键值对. NAME都大写，分号;开始行是注释</font></p>
<h5>
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>;&nbsp;sc.ini&nbsp;file&nbsp;</span><span class="keyword">for</span><span>&nbsp;dmd &nbsp;&nbsp;</span></span> </li>
    <li class=""><span>;&nbsp;Names&nbsp;enclosed&nbsp;by&nbsp;%%&nbsp;are&nbsp;searched&nbsp;</span><span class="keyword">for</span><span>&nbsp;in&nbsp;the&nbsp;existing&nbsp;environment &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>;&nbsp;and&nbsp;inserted.&nbsp;The&nbsp;special&nbsp;name&nbsp;%</span><span class="annotation">@P</span><span>%&nbsp;is&nbsp;replaced&nbsp;with&nbsp;the&nbsp;path &nbsp;&nbsp;</span> </li>
    <li class=""><span>;&nbsp;to&nbsp;</span><span class="keyword">this</span><span>&nbsp;file. &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>[Environment] &nbsp;&nbsp;</span> </li>
    <li class=""><span>LIB=</span><span class="string">&quot;%@P%\..\lib&quot;</span><span>;\dm\lib &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>DFLAGS=</span><span class="string">&quot;-I%@P%\..\src\phobos&quot;</span><span>&nbsp;&nbsp;</span> </li>
    <li class=""><span>LINKCMD=</span><span class="string">&quot;%@P%\..\..\dm\bin&quot;</span><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>DDOCFILE=mysettings.ddoc&nbsp;&nbsp;</span> </li>
</ol>
</div>
</h5>
<h5>8 常见按照问题</h5>
<p><font face="Arial">Using Cygwin's unzip utility has been known to cause strange problems.<br />
Running the compiler under Cygwin's command shell has been also known to cause problems. Try getting it to work under the regular Windows shell cmd.exe before trying Cygwin's.<br />
dmd和dmc按装目录带空格会有问题。<br />
General一般性说明</font></p>
<p><font face="Arial"><strong>1 D接口文件</strong></font></p>
<p><font face="Arial">当处理源文件中的import声明时，编译器会搜索import对应的源文件，从中提取出需要的信息。编译器同时也会搜索D接口文件，D接口文件中只包含模块中需要导入的内容，而不是整个模块。<br />
使用D接口文件的好处是：</font></p>
<p><font face="Arial">D接口文件更小，和D源文件相比处理起来更快。<br />
可以隐藏源代码。比如以接口文件和object库的方式提供源程序，而不是提供全部源代码。</font></p>
<p><font face="Arial">D接口文件可以在编译D源文件时用-H开关创建，D接口文件的后缀是.di。当编译器分解import声明时，搜索寻找.di形式的D接口文件，再寻找D源文件。<br />
D接口文件有点和C++头文件相似，但这不是必需的，它不属于D语言，只是编译器的一个功能，只是用来优化程序的构建。</font></p>
<p>&nbsp;</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/111667#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 13 Aug 2007 10:53:00 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/111667</link>
        <guid>http://sofire.javaeye.com/blog/111667</guid>
      </item>
      <item>
        <title>Build编译工具学习笔记：常用命令参数和BRF文件</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/111460" style="color:red;">http://sofire.javaeye.com/blog/111460</a>&nbsp;
          发表时间: 2007年08月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          build工具的主页在：http://www.dsource.org/projects/build<br />它以前叫 bud，所以这里混用 bud 和build，都指的同一个东西<br /><br />build是D语言的编译工具，相当于C的make命令。<br />但它更简单且好用，因为它能处理 import 语句，自动载入依赖的文件。<br />看过本文后，基本上可以使用了。<br />如果你想用它的高级功能，当然还得花时间去研究它。<br /><br />build 会涉及的文件有：<br />  <strong>brf文件 </strong>（Build Response File） -- bud命令的参数文件<br />  源文件的 Pragmas 指令<br />  rdf文件 （Rule Definition File） -- 规则定义文件<br />  mdf文件 （Macro Definition File） -- 宏定义文件<br />  cfg文件 （Configuration File） -- 配置文件<br />  pfl文件 （Profile File） -- 配置文件？<br /><br />其中，brf文件里面写的就是一些build命令的参数，所以，先从参数开始。<br /><br />先看几个简单参数，然后再说说brf文件，最后把其他参数简单的列一下。<br />[注：以下在Linux和dmd下测试过，没有测试win和gdc]<br /><br />build命令的格式是：<br /><br /><pre name="code" class="java">
build &lt;sourcefile> [&lt;switches> ] [&lt;otherfiles> ]
sourcefile   一般是包括main函数的源文件
switches     上面列出的参数
otherfiles   链接库，object文件，宏定义文件等等其他文件（猜的：））
</pre><br />参数和源文件都没有顺序，可以任意排列 -- 喜欢把源文件放前面，编译参数放后面，因为编译参数经常改<br /><br /><span style="font-size: 16pt"><strong>Bud的常用参数之一：常规选项</strong></span><br /><pre name="code" class="java">
-exec         	编译成功后，运行它
-cleanup      	在编译完成后，把生成的中间文件删除掉，比如 .o 文件
-full         	编译所有的文件，即使没有修改也要编译一遍
-T&lt;name>      	指定目标的文件名
-od&lt;path>     	指定.o 等临时文件的输出目录

-silent      	安静模式，不输出多余信息
-test         	只是显示要调用的命令，不实际编译
-v            	build 和 dmd 都是调试模式
-V            	build 是调试模式，但dmd命令不是
-info         	显示build命令的版本号等信息
-names       	显示要编译的文件名
-uses[=fname]	输出交叉引用文件			
</pre><br /><br /><span style="color: red"><br />如果不是bud的参数，会传递给dmd。比如可以指定 -op -L-l 参数 [注：猜的，不肯定]<br /></span><br /><br />命令参数如果是一个横线（-），表示启用，如果是两个横线（--），表明禁用。<br />比如： bud --cleanup -full<br />两个横线（--）一般和brf文件配合使用，表明要禁用brf文件中的某个编译参数<br /><br />给个例子：a.d 和 b.d<br /><pre name="code" class="java">
module a;

import b;
import std.stdio;

void main(char[][] arg)
{
    writef("in Module A: ");
    writefln(arg);
    print_b();
}
</pre><br /><pre name="code" class="java">
module b;

import std.stdio;

void print_b()
{
    writefln("in Module B: b.d");
}
</pre><br /><br />最简单的编译方法：<br /><pre name="code" class="java">
bud a.d
bud a					# 可以不写 .d 后缀
</pre><br />注意，这里不需要指定 b.d，因为a.d中的import起了作用。<br />bud命令会自动处理。是不是很简单？<br /><br />编译后让它运行：<br /><pre name="code" class="java">
bud a.d -exec
bud a.d -execXXX 		# 给个参数XXX
bud a.d -exec"XXX YYY" 	# 给2个参数XXX YYY  ; 在bash下不能正确运行，不知道怎么处理
</pre><br /><br />改个名字：<br /><pre name="code" class="java">
bud a.d -Ta.out          # 文件名是：a.out   ;在命令行下，生成不了a.out，不知道怎么处理;(
bud a.d -Ttest_{Target}  # 文件名是：test_a
</pre><br /><br />如果你不修改a.d或者b.d，多次运行上面的命令，会提示：<br /><pre name="code" class="java">Files are up to date, no build required.</pre><br />这个和make的原理一样，如果你想每次都编译，可以这么办：<br /><pre name="code" class="java">
bud a.d -full
</pre><br /><br />如果看着那么多的.o文件不爽，就把它删掉：<br /><pre name="code" class="java">
bud a.d -clean  	# -clean 是-cleanup的别名
</pre><br /><br />几个调试选项：<br /><pre name="code" class="java">
bud a.d -names   	# 显示要编译的文件名
bud a.d -test    	# 显示dmd和gcc的调用命令
bud .ad -uses=x    	# 生成交叉引用文件，默认文件名是a.use，这里指定为x
bud a.d -v       	# 除了bud的调试信息，还显示dmd编译器的调试信息
bud a.d -V       	# 只显示bud的调试信息
</pre><br /><br />use文件：<br /><pre name="code" class="java">
[USES]
a.d &lt;> /usr/local/src/phobos/std/stdio.d
a.d &lt;> b.d 
b.d &lt;> /usr/local/src/phobos/std/stdio.d
[USEDBY]
/usr/local/src/phobos/std/stdio.d &lt;> a.d 
/usr/local/src/phobos/std/stdio.d &lt;> b.d 
b.d &lt;> a.d
</pre><br />可以看到，有2个标签：[USES] 和[USEDBY]<br />[USES]　　的含义是 A 文件使用了哪些文件<br />[USEDBY]　的含义是 哪些 文件 别 A文件 使用了<br />每行的文件名之间用 &lt;> 分割<br />升序排列<br /><br /><span style="font-size: 16pt"><strong>Bud的常用参数之二：编译选项</strong></span><br />[注：对编译器的术语不是很清楚，会有些表达不清楚。回头研究一下编译术语，再来修改这段】<br />编译过程一般是 a.d (源文件)  -> a.o (object文件) -> a.exe (可执行文件)，这里不讨论预处理等过程<br />object文件还可以编译成 静态链接库(liba.a) 或者 动态链接库(liba.so)<br /><br />a.d 到 a.o 的过程叫编译 过程<br />a.o 到 a.exe 的过程叫 连接过程(link)<br />a.o 到 liba.a/so 的过程叫 lib过程      [注：实在不知道怎么翻译;( ]<br /><br />bud 默认会把有main()或者Winmain()函数的源程序编译成可执行文件；<br />如果没有这两个函数，则会被编译成链接库文件(.a)<br />下面这些选项可以改变这些行为：<br /><strong>不知道怎么生成 .so的文件？</strong><br /><br /><pre name="code" class="java">
-obj          只是创建 object文件（.o），不进行link和lib操作，等同于同时加 -nolink -nolib
-link         即使源文件中没有main()函数，也强制进行连接。
				main()函数一般在链接库中，而不在要编译的源代码中
-nolink       针对有main()函数的源文件：不进行link操作，只生成 .o 文件
-lib          针对有main()函数的源文件：不进行link操作，只生成 .a 文件
-nolib        针对没有main()函数的源文件：不进行lib操作，只生成 .o 文件
-allobj       不懂：（

-LIBOPT       指定要连接的参数
-LIBPATH      指定链接库的目录
-PP           指定除当前路径外的 其他源文件的搜索路径
</pre><br /><br />举例吧：<br /><br /><pre name="code" class="java">
#-obj：只生成.o 文件
bud a.d -obj         # 会同时生成 a.o b.o
bud b.d -obj         # 生成 b.o，不会生成 a.o ;)

#-link：强制连接
bud a.d -obj         # 生成 a.o
bud b.d a.o          # 生成 b 可执行文件

#-nolink：不链接
bud a.d -nolink      # 生成 a.o

#-lib：生成 静态库
bud a.d -lib         # 生成 a.a 为何不是liba.a?

#-nolib: 不生成 静态库
bud b.d -nolib       # 生成 b.o ，而不是 b.a
</pre><br /><br />LIZBOPT的作用不大清楚，把原文的定义列出来吧，偷懒了<br />-LIBOPT<br /> This allows you to pass one or more command line arguments to the librarian. <br /><br /><pre name="code" class="java">
Example: Set the page size to 32Kb
    -LIBOPT-p32
Example: Embedded spaces enclosed in quotes.
    "-LIBOPT -l -i"
</pre><br /><br />-LIBPATH<br />This allows you to add one or more paths to be searched for library files.<br />This might be used when you don't want to permanently update the standard search paths.<br /><br />Example:<br /><pre name="code" class="java">
    -LIBPATH=c:\mylibs;d:\3rdparty;c:\lib\debuglibs
	-LIBPATH=/usr/lib:/usr/local/lib:/usr/local/lib/mysql/  
</pre><br /><br />-PP 举例：<br />把b.d 文件移动 / 目录下，用bud a.d 编译就会提示找不到b.d，ok<br /><pre name="code" class="java">
bud a.d -PP/         # 提示找不到 /b.o，因为编译的b.o生成在了当前目录，而不是根目录
bud a.d -PP/ -op     # 方案1：op是dmd的编译参数，表示在源文件的路径下生成.o文件
bud a.d -PP/ -odobj  # 方案2：把.o文件都输出到 obj 目录下
</pre><br /><br />dmd命令的-L参数：指定<br /><pre name="code" class="java">
-L            		指定一个连接参数，比如：
						-L-lpthread  linux下链接libpthread.so
</pre><br /><br /><span style="font-size: 18pt"><strong> brf文件使用说明 </strong></span><br /><br />brf文件就是定义了各种bud命令参数的集合。<br />文件扩展名是：.brf<br /><br />举例：<br />文件名：final.brf<br /><pre name="code" class="java">
# 生成发行版本		# #符号是brf文件的注释符号
-T{Target}_release  # 应用程序的名字
-release            # Don't generate runtime checks.
-full               # 重新编译所有文件
-cleanup            # 编译完成后清除中间文件
-inline             # 进行内联优化
</pre><br /><br />运行方法：<br /><pre name="code" class="java">
bud a @final      	# 注意@符号
bud a @final --inline	
					# 把inline选项禁用；有警告，不知道原因;(
</pre><br /><br />可以把源文件写到 brf 文件中<br />每行一个编译参数，没有顺序<br />可以用 -- 选项，把brf文件中的参数禁用了<br />不可以像Makefile文件一样，定义多个编译目标。定义多个brf文件吧<br /><br />bud命令的默认brf文件叫 build.brf，如果要使用默认的brf，则可以不用指定文件名：<br /><pre name="code" class="java">
bud @
</pre><br /><br />多放几个例子上来，备忘：<br />来自：http://dlang.group.javaeye.com/group/topic/1072?page=6<br /><pre name="code" class="java">
-cleanup     		编译后清理掉.o文件  
-L-lpthread 		linux下链接libpthread.so  
-LIBPATH=c:\db 		设置库链接路径  
libdb45.lib  		直接链接windows下使用的lib文件  
-op          		.o文件输出到源文件所在路径  
-odobjs     	 	把.o文件输出到objs文件夹  
-T../bin/test 编译的可执行文件输出路径  
</pre><br /># 一个简单的make.brf 文件<br /><pre name="code" class="java">
-cleanup  
-op  
-L-ldb  
-LIBPATH=/home/lijie/dm/lib:/home/lijie/dmd/lib:/usr/local/BerkeleyDB.4.5/lib  
src/test.d  
-T../bin/test  
</pre><br /><br /><span style="font-size: 18pt"><strong> 其他bud参数 </strong></span><br /><br />如果没有给出定义，就自己看文档吧，我也不大理解 ;)<br /><pre name="code" class="java">
-DCPATH             指定编译器的安装路径
-CFPATH             指定D配置文件的路径
-BCFPATH			指定Bud配置文件的路径

-RDF&lt;file>			指定RDF文件（Rule Definition File）的路径
-MDF&lt;file>			指定MDF文件（Macro Definition File）的路径

-nodef				不创建 MDF（Module Definition File）文件
-explicit			只编译指定的文件
-usefinal			

-dll 		  		如果源文件有DllMain()函数，默认会编译成Dll库；...
-gui				如果源文件有WinMain()函数，默认会编译成GUI程序；...

-help				显示帮助

-AutoWinLibs(=&lt;Yes/No>)
-modules(=&lt;name>)
-UMB=&lt;Yes/No>
-R&lt;option>
-emptyargs          

-M&lt;name>
-X&lt;name>
</pre><br /><br /><span style="font-size: 14pt"><strong>Bud的编译安装</strong></span><br />下载源程序<br />make -f Makefile.unix<br />./build build -full -op<br />ln -s build bud<br /><br />后记：<br />因为我只是用D写写测试程序， 基本上就2、3个文件，最多有个C的链接库。<br />我的这点小需求，bud命令还是能很好处理的。更复杂的情况，我就不了解。<br /><br />文中有些错误，和不肯定的地方，等我弄明白了再来修正吧。
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/111460#comments" style="color:red;">已有 <strong>10</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 12 Aug 2007 23:42:00 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/111460</link>
        <guid>http://sofire.javaeye.com/blog/111460</guid>
      </item>
      <item>
        <title>iconv库函数的学习程序</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/111298" style="color:red;">http://sofire.javaeye.com/blog/111298</a>&nbsp;
          发表时间: 2007年08月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          以前用php的iconv函数，使用起来很简单。<br />用C来写的时候，发现要完全理解了iconv接口才能好程序。<br />一点不直观。也许是因为性能问题吧，它没有封装一个简单的接口。<br />对于懒惰的程序员，还是提供一些简单的接口比较好。<br />因为我们大部分的程序不考虑性能。<br /><br />我现在不是在写D程序，完全是在写DC程序。<br />即要考虑C怎么写，又要考虑D怎么用。<br /><br />附件包括：<br />  学习例程，和libiconv库<br /><br />编译方法：<br />  文件中有一个make.brf文件， 用  bud @make  编译<br /><br />  需要用到iconv库，请从 http://www.gnu.org/software/libiconv/ 下载<br />  我编译的时候用的是iconv-1.11版本，dmd-1.020 linux系统<br /><br /><pre name="code" class="java">
/**
 * iconv 转换库的学习程序
 * Edit by Liu Dehong @ 2007/08/11
 *
 * 参考了libiconv接口
 * 本程序的错误处理设计不好，只是个例子。
 * 完全没有处理常见的错误: 非法字符，内存空间
 * 因为有字符串的复制，性能消耗比较大，考虑完全用D语言改写iconv库，
 * 而不是做封装
 *
 */


/**
* 
* 
* 提供跟 GNU libiconv 库的接口
*
* Name:         libiconvD
* Purpose:      方便在D语言里实现国际编码之间的转换
*
* Author:       张雪平(heromyth)
* Email:        zxpmyth@yahoo.com.cn
* Date:         2007-6-14
* Version:      1.0.1
* Copyrights:   (c) Public Domain and BitWorld Inc.
* Licence:      BSD licence
* 
* Plan:         实现方便在D语言里直接使用的函数或者类
* 
**/

module libiconvD;

alias libiconv iconv ;  ///
alias libiconv_open iconv_open ;  ///
alias libiconv_close iconv_close ; ///


typedef void* iconv_t;

/**
* 设置要转换的编码，并为转换操作准备空间
* 
* Params:
*   fromcode = 需要被转换的源数据的编码格式
*   tocode   = 需要转换成的目标数据的编码格式
* 
* Returns:
*   (iconv_t)(-1)，如果设置有错误；&lt;br>
*   新分配的转换描述信息器，如果设置成功。
* 
* See_Also:
*   iconv_open.3.html
* 
* 注意：
*   参数的顺序一下不能错，否则会造成后面的转换失败
*   所有支持编码可以在参考里找到
*
*/
extern (C) iconv_t libiconv_open (char *tocode, char *fromcode);


/**
* 转换核心函数
* 
* Params:
*   cd             = 转换描述信息器，由libiconv_open提供，可存放转换过程状态
*   inbuf          = 指向源字符序列的第一个位置；在执行后，指向新的空间地址：*inbuf + *inbytesleft
*   inbytesleft    = 源字符序列的字节数；在执行后，通常为0，否则为剩余未被转换的字符数
*   outbuf         = 指向存放目标字符序列的首地址；在执行后，指向新的空间地址：*outbuf + 实际转换的字节数
*   outbytesleft   = 存放目标字符序列的总的空间字节数；剩余的目标空间字节数
* 
* Returns:
*   (iconv_t)(-1) 如果转换有问题；&lt;br>
*   0，调用过程中没有使用可逆转换；&lt;br>
*   其它正数，在一次调用过程中以非可逆方式进行转换的字符数
* 
* 注意：
*   对各个参数含义的理解一定要正确，否则很难正确使用这个函数
*
*/
extern (C) size_t libiconv (iconv_t cd, char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);


/**
* 释放先前申请的准备空间
* 
* Params:
*   cd = 指向先前由libiconv_open申请的转换描述信息器空间
*
*/
extern (C) int libiconv_close (iconv_t cd);

import std.stdio;
import std.c.string;
import std.string;
import std.c.stdlib;

char[] utf8_to_gb2312(char[] str)
{
    return code_conver("utf-8", "gb2312", str);
}

char[] gb2312_to_utf8(char[] str)
{
    return code_conver("gb2312", "utf-8", str);
}

char[] code_conver(string from, string to, in char[] in_str)
{
    auto cd = iconv_open(toStringz(to), toStringz(from));
    if (cd == cast(iconv_t)-1)
    {
        throw new Error("Can't Open from " ~ from ~ " to " ~ to);
        writefln("aaaa");
    }

	uint in_len = in_str.length;
	auto inp = toStringz(in_str);

	uint out_len = 2 * in_len;   // may be enough
	char* outp = cast(char*) malloc(out_len * char.sizeof);
    auto old_outp = outp;

    debug (1) {
    writefln("in_str.ptr: %s", in_str.ptr);
    writefln("inp: %s", inp);
    writefln("oup: %s", outp);
    }

    auto old_in_len = in_len;
    auto old_out_len = out_len;
    auto i = iconv(cd, &inp, &in_len, &outp, &out_len);
    auto conv_len = old_out_len - out_len;

	iconv_close(cd);

    debug (1) {
    writefln("i: %s", i);
    writefln("inp: %s", inp);
    writefln("oup: %s", outp);
    writefln("in_len: %s", in_len);
    writefln("out_len %s", out_len);
    }

    debug (1) {
    //printf("%s", inp);
    printf("inp: %s"\n, inp - old_in_len);
    printf("outp: %s"\n, outp - conv_len);
    }

    auto ret = toString(old_outp).dup;
    free(old_outp);

    return ret;
}

void main()
{

    try
    {
        auto str1 = utf8_to_gb2312("aabb我bb");
        printf("return: %.*s"\n, str1);

        auto str2 = gb2312_to_utf8(str1);
        printf("return: %.*s"\n, str2);
    }
    catch (Error err)
    {
        writefln("catch error: %s", err);
    }

    return ;
}

</pre>
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/111298#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 11 Aug 2007 23:40:12 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/111298</link>
        <guid>http://sofire.javaeye.com/blog/111298</guid>
      </item>
      <item>
        <title>用expat 库解析XML的学习例子</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/110949" style="color:red;">http://sofire.javaeye.com/blog/110949</a>&nbsp;
          发表时间: 2007年08月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          用bcdgen转换的头文件。<br />对xml不大感兴趣。只是尝试用D语言改写，证明它还是能正确处理xml的。<br />和C程序差不多。真不爽。<br /><br /><pre name="code" class="java">
/**
 * expat 中的例子改写成D语言
 * Edit By Liu Dehong @ 2007/08/10
 * version: 1.0
 */

import std.stdio;
import std.stream;
import bcd.expat.xmlparse;

extern(C)
void startElement(void* userData, XML_Char* name, XML_Char** atts)
{
    int i;
    int *depthPtr = cast(int *) userData;

    for (i = 0; i &lt; *depthPtr; i++)
        putchar('\t');

    printf("%.*s\n", name);
    *depthPtr += 1;
}

extern(C)
void endElement(void *userData, XML_Char *name)
{
    int *depthPtr = cast(int*) userData;
    *depthPtr -= 1;
}

int main()
{
    int done;
    int depth = 0;
    XML_Parser parser;

    string fn = "a.xml";
    File f = new File(fn);

    parser  = XML_ParserCreate(null);
    XML_SetUserData(parser, &depth);
    XML_SetElementHandler(parser, cast(XML_StartElementHandler)
            &startElement, cast(XML_EndElementHandler) &endElement);

    while (!f.eof())
    {
        string line = f.readLine();
        //writefln(line, line.length);

        if (!XML_Parse(parser, cast(char*) line, line.length, done)) 
        {
            fprintf(stderr,
            "%s at line %d\n",
            XML_ErrorString(XML_GetErrorCode(parser)),
            XML_GetCurrentLineNumber(parser));
            return 1;
        }
    }

    XML_ParserFree(parser);
    return 0;
}

</pre>
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/110949#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 10 Aug 2007 17:20:45 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/110949</link>
        <guid>http://sofire.javaeye.com/blog/110949</guid>
      </item>
      <item>
        <title>memcached函数的学习程序</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/110836" style="color:red;">http://sofire.javaeye.com/blog/110836</a>&nbsp;
          发表时间: 2007年08月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          尝试把 libmemcached的示例程序改成D语言的。<br />源程序 和示例程序可以从 这里下载：<br />http://people.freebsd.org/~seanc/libmemcache/<br />也可以从附件下载<br /><br />本程序使用了bcd程序来转换c语言的头文件。<br />转换后的memcache.h为 bcd.libmemcache.memcache<br />有几个函数和类型没有转换（？），手动添加进去的。<br /><br />编译方法为：<br />先把libmemcache装上，默认装到/usr/local下<br />然后用：<br />dmd memcached.d /usr/local/lib/libmemcache.a<br /><br />PS：libmemcache的错误捕捉方法，见 libmemcache包中的test目录下的相关程序<br />该lib包的文档不多，多阅读test下的示例代码吧。<br />源程序看起来比较痛苦。<br /><br /><pre name="code" class="java">
/**
 * Memcached的应用程序
 * Edit by Liu Dehong @ 2007/08/09
 * Version:
 *  1.0.0
 */

import std.stdio;
import std.c.stdlib;
import std.string;
import std.socket;
import bcd.libmemcache.memcache;

void main()
{
    /* Create a new memcache instance */
    memcache *mc = mc_new();

    /* Add a few servers */
    mc_server_add(mc, "127.0.0.1", "11211");
    mc_server_add(mc, "127.0.0.1", "11212");
    mc_server_add4(mc, "127.0.0.1:11213");

    char[] key = "key";
    char[] val = "100";
    int expire = 100;
    int flags  = 0;

    /* Add a key */
    mc_add(mc, toStringz(key), key.length, toStringz(val), val.length, expire, flags);

    /* Get a key, caller has to free(3) memory */
    void *blah = mc_aget(mc, toStringz(key), key.length);
    printf("%s"\n, blah);
    auto myval = toString(cast(char*)blah).dup;
    writefln("%s", myval);
    free(blah);

    char[] key1 = "key1";
    char[] key2 = "key2";
    /* Perform a multi-key request */
    memcache_req *req = mc_req_new();
    mc_req_add(req, toStringz(key1), key1.length);
    mc_req_add(req, toStringz(key2), key2.length);
    mc_get(mc, req);
    /* Process the results (need a better interface to looping through results) */

    /* Perform a multi-key request the easy way (this is my preferred way of getting data): */
    req = mc_req_new();
    auto res1 = mc_req_add(req, toStringz(key1), key1.length);
    auto res2 = mc_req_add(req, toStringz(key2), key2.length);
    mc_get(mc, req);
    /* Play with res1/res2 w/o any looping through req */


    /* Complex multi-key get example: */
    /* Grab the response object that will be used to store a given key */
    char[] key3 = "key3";
    memcache_res *res = mc_req_add(req, toStringz(key3), key3.length);
    res.size = 1024;               /* Allocate our own memory a head of time (useful for loops) */
    res.val = malloc(res.size);
    mc_res_free_on_delete(res, 1);

    /* Perform the get */
    mc_get(mc, req);
    mc_res_free(req, res);

    /* Get stats from the whole cluster */
    memcache_server_stats *s = mc_stats(mc);
    mc_server_stats_free(s);

    /* Storage commands: */
    mc_add(mc, toStringz(key), key.length, toStringz(val), val.length, expire, flags);
    mc_replace(mc, toStringz(key), key.length, toStringz(val), val.length, expire, flags);
    //mc_replace(mc, key, key_len, val, bytes, expire, flags);
    mc_set(mc, toStringz(key), key.length, toStringz(val), val.length, expire, flags);

    int hold_timer = 0;
    /* Delete commands: */
    mc_delete(mc, toStringz(key), key.length, hold_timer);

    /* Atomic opts: */
    mc_incr(mc, toStringz(key), key.length, 10);
    mc_decr(mc, toStringz(key), key.length, 5);

    printf("%s"\n, mc_aget(mc, toStringz(key), key.length));

    mc_free(mc);
}
</pre>
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/110836#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 10 Aug 2007 12:26:54 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/110836</link>
        <guid>http://sofire.javaeye.com/blog/110836</guid>
      </item>
      <item>
        <title>QQWry.datIP地址库的查询程序</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/110482" style="color:red;">http://sofire.javaeye.com/blog/110482</a>&nbsp;
          发表时间: 2007年08月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          改写了QQIP地址库的查询程序，学习了怎么操作文件。<br />也学会了正确使用tar命令。<br />本来想把 ip.d ip.php 和 QQWry.dat 文件打包成 a.tgz的，<br />结果把命令写成了 tar czf ip.d ip.php QQWry.dat a.tgz<br />把辛辛苦苦的写的程序给覆盖了：（<br />重新写了一遍，发现还是很快的。<br /><br /><pre name="code" class="java">/**
 * QQWry.dat IP地址库的查找程序
 * Edit by Liu Dehong @ 2007/08/08
 * Version: 1.0.0
 *
 * 改编自 马秉尧 的PHP程序
 * QQWry.dat 来自于 CZ88.net
 * Q数据库的格式参考：http://www.pconline.com.cn/pcedu/empolder/gj/java/0505/612860.html
 */

import std.stdio;
import std.stream;
import std.string;
import std.math;

extern(C)
{
    uint ntohl(uint);
    uint inet_addr(char *cp);
    uint  htonl(uint hostlong);
    char* inet_ntoa(in_addr);
    struct in_addr
    {
        uint s_addr;
    }
}

uint ip2long(char[] ip)
{
    return ntohl(inet_addr(toStringz(ip)));
}

char[] long2ip(ulong ip)
{
    in_addr myaddr;
	myaddr.s_addr = htonl(ip);
	return toString(inet_ntoa(myaddr)).dup;
}

class IpLocation
{
    private File m_file;
    private uint m_firstip;          // 第一条IP记录的偏移地址
    private uint m_lastip;           // 最后一条IP记录的偏移地址
    private uint m_totalip;          // IP记录的总条数（不包含版本信息记录）

    static assert (int.sizeof == 4);
    static assert (uint.sizeof == 4);
    static assert (long.sizeof == 8);

    /* 从文件读取4个字节，返回整型数
     */
    uint get4Byte() 
    {
        uint i;
        m_file.read(i);
        return i;
    }
    
    /* 从文件读取3个字节的数据，返回整型数
     */
    uint get3Byte() 
    {
        ubyte c;
        uint sum;
        int[3] pow = [1, 256, 256*256];
        /**
         * 如读取的是 2 34 56 ，则结果是 2 + 34*256 + 56*256*256
         */
        for (int i; i &lt; 3; i++)
        {
            m_file.read(c);
            sum += c * pow[i];
        }
        return sum;
    }
    
    /* 返回读取的字符串
     */
    char[] getString() 
    {
        debug(1) writefln("GetString's pos: %d(%X)", m_file.position, m_file.position);

        ubyte c;
        char[] str = new char[100]; // guess
        int i;
        for (i = 0; true; i++)
        {
            m_file.read(c);
            if (c == 0)                     // 字符串按照C格式保存，以\0结束
                break;
            if (i == str.length)
                str.length = str.length * 2;
            str[i] = c;
        }
        str.length = i;
        return str;
    }

    /* 返回地区信息
     */
    char[] getArea() 
    {
        debug(1) writefln("GetArea's pos: %d(%X)", m_file.position, m_file.position);

        ubyte flag;                         // 标志字节
        char[] area;

        m_file.read(flag);
        switch (flag) 
        {
        case 0:      
            // 没有区域信息
            area = "";
            break;

        case 1:
        case 2:                             
            // 标志字节为1或2，表示区域信息被重定向
            m_file.position(get3Byte());
            area = getString();
            break;

        default: 
            // 否则，表示区域信息没有被重定向
            area = cast(char)flag ~ getString();      // flag 是一个字符
            break;
        }
        return area;
    }
    
    /* 根据所给 IP 地址或域名返回所在地区信息
     * 索取区按照地址从小到大排列，用折半算法查找
     */
    string[string] getLocation(char[] addr) 
    {
        if ( ! m_file.readable) 
            return null;

        /* 查找纪录区的位置
         */
        uint l = 0;                         // 搜索的下边界
        uint u = m_totalip;                 // 搜索的上边界
        uint findip = m_lastip;             // 如果没有找到就返回最后一条IP记录（QQWry.Dat的版本信息）
        uint i;

        uint beginip;
        uint endip;

        auto ip_t = ip2long(addr);

        while (l &lt;= u)                      // 当上边界小于下边界时，查找失败
        {                  
            i = std.math.lround((l + u) / 2);  
            m_file.position(m_firstip + i * 7);
            m_file.read(beginip);
            if (ip_t &lt; beginip) 
            {
                u = i - 1; 
            }
            else 
            {
                m_file.position(get3Byte());
                m_file.read(endip);
                if (ip_t > endip) 
                {
                    l = i + 1;
                }
                else 
                {
                    findip = m_firstip + i * 7;  // find it
                    break;
                }
            }
        }
    
        debug(1) writefln("Findip is: %d(%#X)", findip, findip);

        /* 获取查找到的IP地理位置信息
         */

        string[string] location;
        m_file.position(findip);
        location["beginip"] = long2ip(get4Byte());          // 用户IP所在范围的开始地址

        auto offset = get3Byte();
        m_file.position(offset);
        location["endip"] = long2ip(get4Byte());            // 用户IP所在范围的结束地址
        
        ubyte flag1, flag2;                 // 标志字节
        m_file.read(flag1);    
        switch (flag1) 
        {
        case 1:
            // 标志字节为1，表示国家和区域信息都被同时重定向
            auto countryOffset = get3Byte();                // 重定向地址
            m_file.position(countryOffset);
            m_file.read(flag2);    // 标志字节
            switch (flag2) 
            {
            case 2:
                // 标志字节为2，表示国家信息又被重定向
                m_file.position(get3Byte());
                location["country"] = getString();
                m_file.position(countryOffset + 4);
                location["area"] = getArea();
                break;

            default:
                // 否则，表示国家信息没有被重定向
                location["country"] = cast(char)flag2 ~ getString();  // flag2 是一个字符
                location["area"] = getArea();
                break;
            }
            break;

        case 2:
            // 标志字节为2，表示国家信息被重定向
            m_file.position(get3Byte());
            location["country"] = getString();
            m_file.position(offset + 8);                    // IP地址(4B) + 定向模式(1B) + 偏移地址(3B)
            location["area"] = getArea();
            break;

        default:
            // 否则，表示国家信息没有被重定向
            location["country"] = cast(char)flag1 ~ getString();      // flag1是一个字符
            location["area"] = getArea();
            break;
        }

        debug(1) writefln("Flag1&2 : %d %d", flag1, flag2);

        if (location["country"] == " CZ88.NET")             // CZ88.NET表示没有有效信息
        {
            location["country"] = "unkown";
        }
        if (location["area"] == " CZ88.NET") 
        {
            location["area"] = "";
        }
        return location;
    }
    
    /**
     * 构造函数，打开 QQWry.Dat 文件并初始化类中的信息
     */
    this(char[] filename = "QQWry.Dat") 
    {
        m_file      = new File(filename);
        m_firstip   = get4Byte();
        m_lastip    = get4Byte();
        m_totalip   = (m_lastip - m_firstip) / 7;
    }

    uint firstip()
    {
        return m_firstip;
    }
    uint lastip()
    {
        return m_lastip;
    }
    uint totalip()
    {
        return m_totalip;
    }
}

void main()
{

    auto ipObj = new IpLocation;

    writefln("First IP is: %s", ipObj.firstip);
    writefln("Last IP is : %s", ipObj.lastip);
    writefln("Total ip is: %s", ipObj.totalip);
    
    string[] myips = [
        "0.255.255.255",
        "0.255.255.255",
        "1.255.255.255",
        "4.10.255.255",
        "4.10.255.255",
        "4.19.77.255",
        "59.57.7.206",
        "222.79.141.30",
        "211.100.32.245",
        "202.106.184.145",
        "202.205.82.122",
        "0.1.163.136",
    ];

    string[string] loc;
    foreach (int k, string v; myips)
    {
        loc = ipObj.getLocation(v);
        printf("%*s in [%.*s ~ %.*s]"\n, v, loc["beginip"], loc["endip"]);
        printf("Country: %-20.*s Area: %-20.*s"\n, loc["country"], loc["area"]);
    }
}
</pre>
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/110482#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 09 Aug 2007 10:13:45 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/110482</link>
        <guid>http://sofire.javaeye.com/blog/110482</guid>
      </item>
      <item>
        <title>ip2long和long2ip的学习程序</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/110118" style="color:red;">http://sofire.javaeye.com/blog/110118</a>&nbsp;
          发表时间: 2007年08月08日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          这2个是PHP里面的常用函数，用D重新包装了一下。<br />虽然可以使用，但没有错误判断。<br /><br />顺便练习了一下C字符串和D字符串之间的转换。<br /><br /><pre name="code" class="java">
import std.stdio;
import std.string;

extern(C)
{
    uint ntohl(uint);
    uint inet_addr(char *cp);
    uint  htonl(uint hostlong);
    char* inet_ntoa(in_addr);
    struct in_addr
    {
        uint s_addr;
    }
}

ulong ip2long(char[] ip)
{
    return ntohl(inet_addr(toStringz(ip)));
}

char[] long2ip(ulong ip)
{
    in_addr myaddr;
	myaddr.s_addr = htonl(ip);
	return toString(inet_ntoa(myaddr));
}

void main()
{
    char* c_str1;
    char* c_str2;
    char* c_str3;
    char[] d_str1;
    char[] d_str2;
    char[] d_str3;

    c_str1 = "C string";
    d_str1 = "D string";

    // C字符串 转换到 D字符串
    d_str2 = toString(c_str1);

    writefln("c to d: %s", d_str2);
    printf("c to d: %.*s"\n, d_str2);

    // D字符串 转换到 C字符串
    c_str2 = cast(char*) (d_str1 ~ "\0");
    c_str3 = toStringz(d_str1);

    printf("d to c: %s"\n, c_str2);
    printf("d to c: %s"\n, c_str3);
    
    // cast(char*)转换和直接str.ptr是一样的，不保证有\0结尾，除非运气好刚好碰上一个。
    //c_str2 = cast(char*) (d_str1); //error
    //printf("%s"\n, d_str1.ptr);   // error

    writefln(ip2long("192.0.34.166"));
    writefln(long2ip(3221234342));
}
</pre>
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/110118#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 08 Aug 2007 13:00:05 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/110118</link>
        <guid>http://sofire.javaeye.com/blog/110118</guid>
      </item>
      <item>
        <title>md5函数的学习程序</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/109748" style="color:red;">http://sofire.javaeye.com/blog/109748</a>&nbsp;
          发表时间: 2007年08月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          前面部分是库文件里面的例子，后面是我改的。<br />写起来和PHP差不多简单。呵呵，有例子就是好。<br /><br />源程序里面定义编译不了：<br />    ubyte[4 * 1024] buffer;<br />我改成了<br />    ubyte[] buffer;<br />    buffer.length = 4 * 1024;<br />也许下面的写法更好些，谁知道呢？<br />    ubyte[] buffer = new ubyte[4 * 1024];<br /><br />代码如下：<br /><br /><pre name="code" class="java">// This code is derived from the
// RSA Data Security, Inc. MD5 Message-Digest Algorithm.

import std.md5;

private import std.stdio;
private import std.string;
private import std.c.stdio;
private import std.c.string;

int main(char[][] args)
{
    foreach (char[] arg; args)
     MDFile(arg);

    MDString("Hello, D");

    return 0;
}

/* Digests a file and prints the result. */
void MDFile(char[] filename)
{
    FILE* file;
    MD5_CTX context;
    int len;
    //ubyte[4 * 1024] buffer;
    ubyte[] buffer;
    buffer.length = 4 * 1024;
    ubyte digest[16];

    if ((file = fopen(std.string.toStringz(filename), "rb")) == null)
    {
        writefln("%s can't be opened", filename);
    }
    else
    {
        context.start();
        while ((len = fread(cast(void*) buffer, 1, buffer.sizeof, file)) != 0)
            context.update(buffer[0 .. len]);
        context.finish(digest);
        fclose(file);

        writefln("MD5 File (%s) = %s", filename, digestToString(digest));
    }
}

/* Digest a string and prints the result. */
void MDString(char[] str)
{
    MD5_CTX context;
    ubyte digest[16];

    if (str.length)
    {
        context.start();
        context.update(str);
        context.finish(digest);

        if (str.length > 10)
            writefln("MD5 String (%s..) = %s", str[0..10], digestToString(digest));
        else
            writefln("MD5 String (%s) = %s", str, digestToString(digest));
    }
}
</pre>
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/109748#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 07 Aug 2007 15:52:00 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/109748</link>
        <guid>http://sofire.javaeye.com/blog/109748</guid>
      </item>
      <item>
        <title>超人，请接受我的请求，人类的心脏更脆弱</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/109745" style="color:red;">http://sofire.javaeye.com/blog/109745</a>&nbsp;
          发表时间: 2007年08月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          本来写好的文章，结果因为不接受我的文件格式而失败。<br /><br />文件格式只能是“jpg,gif,png,bmp格式的图片和zip,rar格式的压缩文件”，<br />结果我把D语言的程序上传上去，就出现提示：<br />“<br />超人，您的请求服务器暂时无法响应，请体谅人类服务器脆弱的心脏吧。<br />”<br /><br />返回就发现文章内容没有了。ft
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/109745#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 07 Aug 2007 15:35:02 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/109745</link>
        <guid>http://sofire.javaeye.com/blog/109745</guid>
      </item>
      <item>
        <title>writef和printf函数的学习程序</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/109741" style="color:red;">http://sofire.javaeye.com/blog/109741</a>&nbsp;
          发表时间: 2007年08月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          和C函数的格式相同。<br /><br />只是printf和writef中的 s 意思不一样<br /><br />不知道C语言中是否有用 * 号来表示宽度和精度。<br />D语言中，可以用*号来表示。它需要对应个数字，像 %d一样要对应一个数字。<br />如 <br />  ("%*d", 5, 1)   相当于 ("%5d", 1)  表示宽度<br />  ("%.*d", 5, 1)  相当于 ("%.5d", 1) 表示精度<br /><br />正好，char[] 表示的是长度和字符串。<br />和 %*s %.*s 吻合<br />所以可以用在printf函数中表示D语言的一个char[] 类型<br />不知道这2种形式有没有啥区别，但只是都能正常显示。<br /><br />附上代码：<br /><br /><pre name="code" class="java">
import std.stdio;
import std.string;
import std.c.string;

class A
{
}

void main()
{
    char[] str;

    str = "abcde";

    str ~= "\0";
    printf("string(%d) '%s'\n", strlen(cast(char*)str), cast(char*)str);
    writefln("string(%d) :%s", str.length, str);

    str = "edcba";
    printf("string(%d) '%s'\n", strlen(cast(char*)str), toStringz(str));
    writefln("string(%d) :%s", str.length, str);
    writefln("%s", str);

    // 区别
    printf("the string is '%.*s'\n", "aaaaaaaaaaaaa我");
    printf("the string is '%*s'\n", "aaaaaaaaaaaaa我");

    int a = 456;
    printf("d: %d %05d %+d |%-5d| |%5d| |% d| |% d|"\n, a, a, a, a, a, a, -a);        // 十进制
    writef("d: %d %05d %+d |%-5d| |%5d| |% d| |% d|"\n, a, a, a, a, a, a, -a);        // 十进制
    printf("*: |%*d| |%-*d| |%.*d| |%*.d|"\n, 5, a, 5, a, 5, a, 5, a);
    writef("*: |%*d| |%-*d| |%.*d| |%*.d|"\n, 5, a, 5, a, 5, a, 5, a);

    printf("u: %u %05u %+u |%-5u| |%5u|"\n, a, a, a, a, a);        // 十进制无符号
    //writef("u: %u %05u %+u |%-5u| |%5u|"\n, a, a, a, a, a);        // 十进制无符号
    //
    printf("o:  %o %#o"\n, a, a);        // 八进制
    writef("o:  %o %#o"\n, a, a);        // 八进制

    printf("x: %X %x %#x %#X %05x |%-5x|"\n, a, a, a, a, a, a);        // 十六进制
    writef("x: %X %x %#x %#X %05x |%-5x|"\n, a, a, a, a, a, a);        // 十六进制

    float f = 2.1, f2 = 2222222, f3 = 0.1111111111;
    printf("f: %f |%.3f| |%5f| |%3.5f| |%5.3f|"\n, f, f2, f3, f, f);        // 浮点数
    writef("f: %f |%.3f| |%5f| |%3.5f| |%5.3f|"\n, f, f2, f3, f, f);        // 浮点数

    float e = 2.1, e2 = 2222222, e3 = 0.1111111111;
    printf("e: %e |%.3e| |%5e| |%3.5e| |%5.3e|"\n, e, e2, e3, e, e);        // 指数
    writef("e: %e |%.3e| |%5e| |%3.5e| |%5.3e|"\n, e, e2, e3, e, e);        // 指数

    printf("g: %g |%.3g| |%5g| |%3.5g| |%5.3g|"\n, e, e2, e3, e, e);        // 十六进制
    writef("g: %g |%.3g| |%5g| |%3.5g| |%5.3g|"\n, e, e2, e3, e, e);        // 十六进制

    printf("a: %a |%.3a| |%5a| |%3.5a| |%5.3a|"\n, e, e2, e3, e, e);        // 不懂
    writef("a: %a |%.3a| |%5a| |%3.5a| |%5.3a|"\n, e, e2, e3, e, e);        // 不懂

    // * 号作为宽度标志和精度标志
    printf("*: |%*f| |%-*f| |%.*f| |%*.f| |%*.*f|"\n, 5, e, 5, e, 5, e, 5, e, 8, 3, e);
    writef("*: |%*f| |%-*f| |%.*f| |%*.f| |%*.*f|"\n, 5, e, 5, e, 5, e, 5, e, 8, 3, e);

    A aa = new A;
    int[] ab = [1, 2, 3];
    writef("s: %s %s %s %s %s %s", true, -10, -2.0001, "abc", aa, ab);

}

</pre>
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/109741#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 07 Aug 2007 15:29:55 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/109741</link>
        <guid>http://sofire.javaeye.com/blog/109741</guid>
      </item>
      <item>
        <title>【备忘】D语言编译器的下载地址、安装方法</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/109524" style="color:red;">http://sofire.javaeye.com/blog/109524</a>&nbsp;
          发表时间: 2007年08月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在D语言主页上，老是找不到编译器的安装程序。<br />后来好不容易一个下载地址，下载后，发现是老版本的1.015<br />今天总算找到全部的下载地址了。<br /><br />http://ftp.digitalmars.com/<br /><br />编译器的安装方法是：<br />http://digitalmars.com/d/dcompiler.html<br /><br />重要的几步是：<br />chmod u+x dmd/bin/{dmd,dumpobj,obj2asm,rdmd}<br /><br />....
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/109524#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 07 Aug 2007 00:09:14 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/109524</link>
        <guid>http://sofire.javaeye.com/blog/109524</guid>
      </item>
      <item>
        <title>base64函数的学习程序</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/109493" style="color:red;">http://sofire.javaeye.com/blog/109493</a>&nbsp;
          发表时间: 2007年08月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">import std.stdio;
import std.base64;

void main()
{
    char[] a;
    char[] b;
    char[] c;

    // 方法1
    a = "%%%abdsfds%";
    a = "张33";
    writefln("a string (%d):\t%s", a.length, a);

    b = encode(a);
    writefln("b string (%d):\t%s", b.length, b);

    c = decode(b);
    writefln("c string (%d):\t%s", c.length, c);

    assert(c == a);

    writefln();

    // 方法2

    char[] d;
    char[] e = new char[100];
    char[] f = new char[100];
    e[] = 0;
    f[] = 0;

    d = "%%%ABCCCC%AFDSFDS%";
    d = "CCCCAAFDSFDSAAAAAA";
    d = "张33";

    writefln("d string (%d):\t%s", d.length, d);

    encode(d, e);
    e.length = encodeLength(d.length);
    writefln("e string (%d):\t%s", e.length, e);

    decode(e, f);
    f.length = decodeLength(e.length);
    writefln("f string (%d):\t%s", f.length, f);

    assert(d == f);
}</pre><br /><br />有两点不清楚：<br />1，最后的assert不正确。不清楚为什么，请教高手。<br /><br />2，方法2的写法正确吗？数组的定义和初始化还不是十分清楚。<br />是不是e[] = 0；是多余的。<br />char[e] = new char[100]; 语句是不是就是分配100个字节空间？<br /><br />这种写法会不会更好一些。<br />char[] e;<br />e.length = encodeLength(d.length);<br /><br />2007年8月7日：<br />去把base64里面的函数调试了一下。发现encodeLength / decodeLength根本不是编码解码后的字符串长度，只是一个最大长度。传入的字符串应该大于等于这个长度，函数才继续执行而已。<br />传入的buffer长度和返回值的长度之间的关系（base64里面的unittestl例子）：<br /><div class="quote_title">引用</div><div class="quote_div">buffer: 3<br />return: f, 1<br /><br />buffer: 3<br />return: fo, 2<br /><br />buffer: 3<br />return: foo, 3<br /><br />buffer: 6<br />return: foos, 4<br /><br />buffer: 33<br />return: all your base64 are belong to foo, 33<br /><br />buffer: 18<br />return: testing some more, 17<br /><br />buffer: 9<br />return: asdf jkl;, 9<br /><br />buffer: 12<br />return: base64 stuff, 12<br /><br />buffer: 18<br />return: foo!, 18<br /></div>
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/109493#comments" style="color:red;">已有 <strong>11</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 06 Aug 2007 20:17:50 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/109493</link>
        <guid>http://sofire.javaeye.com/blog/109493</guid>
      </item>
      <item>
        <title>re：敏捷Web网站开发</title>
        <author>sofire</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://sofire.javaeye.com">sofire</a>&nbsp;
          链接：<a href="http://sofire.javaeye.com/blog/93252" style="color:red;">http://sofire.javaeye.com/blog/93252</a>&nbsp;
          发表时间: 2007年06月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          发现自己可以发言了。<br />
以前老是不能验证邮箱，今天突然可以了。真是奇怪。<br />
<br />
对php比较疲倦了，想看看ror，学习学习。<br />
<br />
-------------------------<br />
这个回复被评为 隐藏贴 了。
          <br/><br/>
          <span style="color:red;">
            <a href="http://sofire.javaeye.com/blog/93252#comments" style="color:red;">已有 <strong>1</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 22 Jun 2007 21:49:00 +0800</pubDate>
        <link>http://sofire.javaeye.com/blog/93252</link>
        <guid>http://sofire.javaeye.com/blog/93252</guid>
      </item>
  </channel>
</rss>