2014年5月12日月曜日

[linux] ソースコードをHTMLに変換するコマンド:enscript

ブログ上でコードを紹介する際、単にコードをコピペしただけだと"<", ">", "&"などの文字が適切に表示されなかったり、タブの位置がずれたり、キーワードがわかりにくかったり、といった問題に遭遇します。
いろいろとツールが出ているようなのですが、linux上であればenscriptというコマンドで容易にhtml化ができることが分かったためその方法を紹介します。


%  enscript --highlight=cpp --color -C -o output.html -w html input.cpp


上記のコマンドでinput.cppの内容がoutput.htmlに出力されます。キーワードをハイライトするオプションである"--color"を指定する際には"--hilight"が必要なので注意が必要です。また、行番号を出力する"-C"はhtmlへの出力時には効かないようです(残念…)。
入力としてサポートしている言語は多岐にわたっています。以下、そのリストになります。
  • ada
  • asm
  • awk
  • bash
  • c
  • changelog
  • cpp
  • csh
  • delphi
  • diff
  • diffs
  • diffu
  • elisp
  • f90
  • fortran
  • fortran_pp
  • haskell
  • html
  • idl
  • inf
  • java
  • javascript
  • ksh
  • m4
  • mail
  • makefile
  • matlab
  • nroff
  • objc
  • outline
  • pascal
  • perl
  • postscript
  • pyrex
  • python
  • rfc
  • ruby
  • scheme
  • sh
  • skill
  • sql
  • states
  • synopsys
  • tcl
  • tcsh
  • tex
  • vba
  • verilog
  • vhdl
  • vrml
  • wmlscript
  • zsh
"-w"で指定する出力フォーマットは以下の通りです。
  • PostScript
    • generate PostScript (default)
  • html
    • generate HTML
  • overstrike
    • generate overstrikes (line printers, less)
  • rtf
    • generate RTF (Rich Text Format)
  • ansi 
    • generate ANSI terminal control codes

(独り言…)haskellもサポート言語に加えてほしいなぁ。失礼しました。ちゃんとhaskellもサポートされていました。

[c++][gcc] constメンバ関数の中でメンバ変数を書き換えるには

C++において、一般的に定数宣言の目的で使用されるconst修飾子ですが、メンバ変数、メンバ関数、引数、返値にも宣言できることはご存知でしょうか。
適切に利用することで、以下のようなメリットが得られます。
  • API仕様がより明確になる
  • コードの可読性・メンテナンス性があがる

これらのメリットを享受すべくconst修飾子を積極的に利用していたのですが、まれにconstメンバ関数の中で、メンバ変数を書き換えたい、もしくは、メンバ変数の関数を呼び出したい、といったケースが発生したことがありました。
これまではconst関数の中でメンバ変数の値は参照のみで書き換えはできないと思っていたのですが「C++のためのAPIデザイン」という書籍を読みmutable修飾子が用意されていることを知りました。

const関数の中でメンバ変数を書き換えようとすると以下のようなエラーになります。

const_test.cpp: In member function 'void ConstTest::constFunc(int) const':
const_test.cpp:11:9: error: assignment of member 'ConstTest::m_val' in read-only object
   m_val = val;
         ^
const_test.cpp:12:23: error: passing 'const NotConst' as 'this' argument of 'void NotConst::normalFunc()' discards qualifiers [-fpermissive]
   m_normal.normalFunc();
                       ^
これは以下のコードをコンパイルしたときのエラーです(gcc 4.8.2)。
class NotConst
{
public:
 void normalFunc() /*const*/ {}
};
class ConstTest
{
public:
 void constFunc(int val) const
 {
  m_val = val;
  m_normal.normalFunc();
  return;
 }
private:
 /*mutable*/ int m_val;
 /*mutable*/ NotConst m_normal;
};
15行目と16行目でコメントアウトしているmutable修飾子を有効にすると、エラーなくコンパイルが通るようになります。mutable修飾子が付与されている変数を見かけたときには「const宣言されたオブジェクトでも変更されることがありますよ」と理解しましょう。

ちなみに後者のエラーは、NotConst::normalFunc()をconst関数に変更することでも修正が可能です。normalFunc()の仕様としてconst関数が適切なのであれば、mutable宣言を用いるのは避けてconst関数化すべきです。