HTML文書でhタグに自動連番見出しを振る方法

body
{
    counter-reset: chapter;
    counter-reset: section;
    counter-reset: detail;
}

h1
{
    counter-reset: chapter;
}

h2
{
    counter-reset: section;
}

h3
{
    counter-reset: detail;
}

h2:before
{
    content: counter(chapter) ". ";
    counter-increment: chapter;
}

h3:before
{
    content: counter(chapter) "." counter(section) ". ";
    counter-increment: section;
}

h4:before
{
    content: counter(chapter) "." counter(section) "." counter(detail) ". ";
    counter-increment: detail;
}

Qt OSS版をMac OS Xにソースコードからインストールしてみた

Mac OS X 10.11.6, Qt 5.8.0, Xcode 7.2

Qtはデュアルライセンスなので、必ずしもGPLで開発しなければならないわけではないが、ここではGPLのプロジェクトとして開発する環境を前提とする。

【ポイント】

  • GPL, LGPLライセンス
  • GCCではなくclang(Xcode)のmakeでコンパイルする
  • GNUのlibtoolのパスを通しておかないこと(Xcodeコマンドラインツールのlibtoolが使われるようにしておく)
  • インストール先を指定する場合、--prefix=path ではなく、-prefix path とする
  • make時に複数コアを使わせてはいけない
  • コンパイルにめっちゃ時間がかかる(私の環境で5時間くらい)


以下、作業ログ

(事前にXcodeコマンドラインツール、wgetコマンドはインストール済み)

$ export QT_HOME=$HOME/path/to/somewhere

# Install Qt by clang with Xcode. (not GCC and GNU softwares.)
$ sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
$ sudo xcodebuild -license
agree

# And path of the GNU libtool must not be passed.
# https://bugreports.qt.io/browse/QTBUG-42835
# It must be Xcode libtool, That is what the following state is correct.
$ which libtool
/usr/bin/libtool
$ libtool -V
Apple Inc. version cctools-877.8

# Now, Let's start installing Qt.
$ cd $QT_HOME/download
$ wget http://download.qt.io/official_releases/qt/5.8/5.8.0/single/qt-everywhere-opensource-src-5.8.0.tar.gz
$ tar xf qt-everywhere-opensource-src-5.8.0.tar.gz
$ cd qt-everywhere-opensource-src-5.8.0

# http://doc.qt.io/qt-5/configure-options.html
# Caution: `--prefix=path` is not correct, `-prefix path` is correct here.
$ ../configure -prefix $QT_HOME

# Type 'o' to install Open Source Edition.
# Type 'yes' to accept LGPL3 and GPL2 license offer.

# > Note: There is a potential race condition when running make install with multiple jobs. 
# > It is best to only run one make job (-j1) for the install.
$ make -j1
# Wait for compile, quite a long time. (about 4-5h)
$ make install

GLib2のインストールに失敗した話

Mac OS X 10.11.6, GCC 6.3.0, GLib 2.52.1

ご存知のようにGLibとpkg-configは相互依存している。願わくば、次に生まれる時には基盤となるようなツールやライブラリーに、相互依存関係というものが存在しない世の中に生まれたい。

結論から言えば、どちらも存在しない状態からpkg-configを入れたいのであれば、以下のように --with-internal-glib オプションを付ければ良い。

# Install pkg-config.
# https://www.freedesktop.org/wiki/Software/pkg-config/
$ cd $MY_PROJECT_ROOT/download
$ wget https://pkg-config.freedesktop.org/releases/pkg-config-0.29.2.tar.gz
$ tar xf pkg-config-0.29.2.tar.gz
$ cd pkg-config-0.29.2
$ mkdir work
$ cd work
$ ../configure --prefix=$MY_PROJECT_ROOT --with-internal-glib
$ make -j8
$ make install

では例えば、pkg-configをインストールせずに、GLibだけインストールしたいとしたらどうするか。

結果負けたけど、途中までは以下の手順で行けていた。

# Install libffi. (that is necessary to build GLib2)
# https://sourceware.org/libffi/
$ cd $MY_PROJECT_ROOT/download
$ wget ftp://sourceware.org/pub/libffi/libffi-3.2.1.tar.gz
$ tar xf libffi-3.2.1.tar.gz
$ mkdir work
$ cd work
$ ../configure --prefix=$MY_PROJECT_ROOT
$ make -j8
$ make install

# Install PCRE - Perl Compatible Regular Expressions. (that is necessary to build GLib2)
# http://www.pcre.org
$ cd $MY_PROJECT_ROOT/download
$ wget https://ftp.pcre.org/pub/pcre/pcre-8.40.tar.gz
$ tar xf pcre-8.40.tar.gz
$ cd pcre-8.40
$ mkdir work
$ cd work
$ ../configure --prefix=$MY_PROJECT_ROOT
$ make -j8
$ make install

# Install gettext. (that is necessary to build GLib2)
# http://www.gnu.org/software/gettext/
$ cd $MY_PROJECT_ROOT/download
$ wget https://ftp.gnu.org/pub/gnu/gettext/gettext-0.19.8.1.tar.xz
$ tar xf gettext-0.19.8.1.tar.xz
$ cd gettext-0.19.8.1
$ mkdir work
$ cd work
$ ../configure --prefix=$MY_PROJECT_ROOT
$ make -j8
$ make install
$ gettext --version
gettext (GNU gettext-runtime) 0.19.8.1

# Install GLib2. (that is necessary to build pkg-config)
# https://developer.gnome.org/glib/
$ cd $MY_PROJECT_ROOT/download
$ wget http://ftp.gnome.org/pub/gnome/sources/glib/2.52/glib-2.52.1.tar.xz
$ tar xf glib-2.52.1.tar.xz
$ cd glib-2.52.1
$ mkdir work
$ cd work
$ LIBFFI_CFLAGS=-I$MY_PROJECT_ROOT/lib/libffi-3.2.1/include LIBFFI_LIBS="-L$MY_PROJECT_ROOT/lib -lffi" PCRE_CFLAGS=-I$MY_PROJECT_ROOT/include PCRE_LIBS="-L$MY_PROJECT_ROOT/lib -lpcre" ../configure --prefix=$MY_PROJECT_ROOT --with-pcre=internal
$ make -j8

# Compile error.

オープンソースソフトウェアを使うなら、当然Cのソースくらい読めないとね。

さて、問題。

gdummymyfile.c内の下記unescape_string関数がコンパイルエラーになるわけだが、これがなぜだか分かるだろうか?

static char*
unescape_string (const gchar *escaped_string,
         const gchar *escaped_string_end,
         const gchar *illegal_characters)
{
  const gchar *in;
  gchar *out, *result;
  gint character;
  
  if (escaped_string == NULL)
    return NULL;

  if (escaped_string_end == NULL)
    escaped_string_end = escaped_string + strlen (escaped_string);
  
  result = g_malloc (escaped_string_end - escaped_string + 1); 
    
  out = result;
  for (in = escaped_string; in < escaped_string_end; in++) 
    {   
      character = *in;
      if (*in == '%') 
        {   
          in++;
          if (escaped_string_end - in < 2)
        {   
          g_free (result);
          return NULL;
        }   
    
          character = unescape_character (in);
    
          /* Check for an illegal character. We consider '\0' illegal here. */
          if (character <= 0 ||
          (illegal_characters != NULL &&
           strchr (illegal_characters, (char)character) != NULL))
        {   
          g_free (result);
          return NULL;
        }   
          in++; /* The other char will be eaten in the loop header */
        }   
      *out++ = (char)character;
    }   
  
  *out = '\0';
  g_warn_if_fail (out - result <= strlen (escaped_string));
  return result;
}

まあ、どう見ても間違えてないよね。

こちらの方の記事に問題の原因と解決方法が示されていた。
http://d-alchemy.xyz/tips/qemu_on_snow_leopard.html

要するに、.cファイルなのに無理矢理Objective-Cとしてコンパイルさせようとしているのが問題というわけだ。

実際、上記の問題の関数を抽出し、一部修正してtest.cとしてgccコンパイルしたらコンパイルできた。全く同じ内容で、test.mとしてgccコンパイルするとエラーになった。


え? でもObjective-CってCのスーパーセットだよね?


そう、そんなことは本来あってはならない。

ということで、Xcode 7.2で同じことをしてみた。
結果、test.cもtest.mもコンパイルできた。

どゆこと?

どうやら問題は、変数inをforループ内で使った時に、Xcodeはきちんと構文を解釈できる。GCCはfor〜in文として見てしまうのでエラーになってしまう。ということらしい。


【問題を局所化した検証コード】
test.m

#include <stdio.h>
#include <string.h>

void func()
{
    const char* psz = "Lorem ipsum dolor sit amet";
    const char* in;
	
    /* for の in = のところでコンパイルエラー */
    for (in = psz + strlen(psz); in >= psz; -- in) {
        printf("%c", *in);
    }
}

int main()
{
    func();
    return 0;
}

なぁんだかねぇ…


この件は誰が悪いの?

  • inなんていう汎用的な語句を予約語にしたObjective-Cが悪い
  • Cocoaが内部のコアなところでObjective-Cなんて使ってるのが悪い
  • .cファイルをObjective-Cコンパイルさせんのやめえや
  • Objective-Cが絡むプロジェクトで変数名 in を使うな? いやいや
  • GCCちゃんってそんなのも構文解析できないの? プークスクス
  • そもそもGLibとpkg-configの相互依存やめろしいややめてくださいお願いします


私が言いたいのは、「時間を返せ」、ということだけだ。

足の怪我

寒いから毎日部屋で鍋をしてたら足を捻挫した。

歩けなくなって困ったわ。

足を引きずりながら整形外科に行ったが、医者からは捻挫ではないと言われた。

不思議だね。


あ、そうそう、全然関係ない話だけど、この人がオススメしてるメニュー、全部大好き。
なんとなく気が合いそうだ。
http://www.life-abstract.com/entry/2016/05/03/083000

発音

仕事中に後輩から発音を注意された。

私「○○くん、EclipseのHTMLバリデーションでワーニング出てるんだけどこれ何だかわかる?」
後輩「ああ、はい、ウォーニングですね?」

ハッ!?

そう、彼が正しい。
こういうのは正しくなければならない。

  • Warning は「ウォーニング」(not ワーニング)
  • ALTERは「オルター」(not アルター
  • NULLは「ナル」(not ヌル)
  • charは「キャラ」(not チャー)
  • wwwは「ダブリュースリー」(not ダボダボダボ)
  • DBは、、、、ディービー…

否!

デービー!

カタカナ英語の法則が乱れる・・・!



最近の悩みは、/var これを「ヴァル」と言うべきか「ヴァー」と言うべきか。
見た目はヴァーだけど、語源がvariableなのかなと思うとヴァルな気もする。

年会費をどう見るか

それが問題だ。
ああ、昨日のクレカの話だ。

まずは毎月確実な出費となる通勤定期券について、確実にポイントを貯められるクレカを入手すべきと私は考えたのだ。真っ先に思いついたのはView Suicaであった。あれは見るからに便利そうだ。

しかし今現在では、View Suicaよりも、ビックカメラSuicaカードの方が良いような気がしてきている。

なぜなら年会費がかからないからだ。私のような低所得者にとって、クレカで貯めるポイントなんてものは微々たるものだ。そんなものは、せいぜい年に1回か2回、iTunesコードに還元して、かわいい2次元の女の子ばかりが擬似乱数によってランダムで当たるバカみたいなゲーム以外に課金するくらいだろう。

年400円程度であっても、それが微々たるものだから無視できるというなら、クレカで貯めるポイント自体が微々たるものということになってしまうではないか。

そこをどう考えるかが問題だ。

ただ、ビックカメラSuicaにしても問題はある。

まず、View Suicaと違って、定期券とクレカを別々に所持しなければならないことであり、その点はやはり一体型になっているView Suicaは魅力的に見える。しかしなんとこのビックカメラSuicaモバイルSuicaに対応しており、通常1000円の年会費が無料になるらしい。なのでそこはiPhoneを新しく買い換えてモバイルSuicaを使えば良いだろう。

さて、別の問題として、ビックカメラSuicaは難しい。私の小卒レベルの頭脳で理解するには、相当難易度が高い。

定期券を更新するだけに使うならまあ問題はない。それはViewポイントとして、1000円につき6ポイント貯まる。つまり1.5%の還元率ということになる。

なるほど、確かに6/1000は1.5%か。

はあ?

意味がわからないよ。

これがどういうことかというと、だ。

ビューサンクスポイントというのは、

  • 1000円のクレジット決済につき2ポイントのビューサンクスポイント還元を基本とする
  • ただし、Suicaの入金、チャージ時はなんとポイント3倍!
  • 400ポイントで1000円分のSuicaに還元できる

例)毎月定期券で10000円、ビックカメラSuicaカードでクレジット決済すると

  • 1000円につき2ポイントだから、10000円で20ポイント
  • Suicaチャージに該当するので3倍として換算されるので、60ポイント
  • ビューサンクスポイント400で1000円だから、1ポイントは2.5円相当
  • 60ポイントは150円相当

ほら、1万円が150円相当になったでしょ!? はい、1.5%です。

まあ実際には400ポイント単位でしかSuicaに還元できないから、現実として150円チャージされるわけではなく、これだけでは0円なのだが、そこは良いだろう。
さすがにそのくらいは私でも理解出来る。

さて、このカードはビックカメラのポイントカードとしての属性も併せ持っている。そして、普段使い(Suica, ビックカメラ以外での買い物時)では両方にポイントがつく。

例)レストランで1000円の食事をして、ビックカメラSuicaカードでクレジット決済すると

  • ビューサンクスポイントが2ポイント貯まる(5円相当)
  • ビックポイントが5ポイント貯まる(5円相当)
  • 合計で10円相当貯まるから1%

ここで注意しなければならないのは、上記は2つの別々のポイントを一緒くたにして「10円相当」と言っているが、これらは別々に2ポイントと5ポイントであることに注意しなければならない。

でもって、ビックカメラでこのカードを使った場合は、現金払いと同様、10%のビックポイント還元である。

ただし、ビックポイントをSuicaに還元する場合は、1500ビックポイントで1000円なので、この場合の1ビックポイントは0.66円(Suica)となる。

ということで、このカードの最大の売りは、Suicaで1万円チャージするとビューサンクスポイントが60pt貯まって、そのチャージした1万でビックカメラで買い物するとビックポイントが1000pt貯まって、60ptのビューサンクスはSuicaに還元すると150円相当で、1000ビックポイントはSuicaに還元すると666円相当だから、この場合は816円くらい儲かることになるんだね。

つまり、ビューサンクスポイントはSuicaにして使えば良いけれども、ビックポイントは普通にビックカメラのポイントとして使った方がお得ではある。汎用性を取る場合は、ビックポイントを0.66倍してSuicaで使うこともできるという話。

はあ、面倒臭いね。本当に。


けど、なんだかんだで、このカードはかなりお得だと思う。
ビックカメラやコジマ(提携店なの?)を使う人にはかなり良い。私の場合は貯まったポイントでiTunesカードを買うつもり*1でいるから、ビックポイントはSuicaに移行せずにそのまま100%使えるので、これはかなりでかい。ただまあ、ビックカメラiTunesコードを買ってもビックポイントは付かないから、その点については11.5%還元戦略は取れないわけだけれども。それにしたって、ビックカメラで時々買い物はするだろうし、そうでなくても、年会費なしで、毎月の通勤定期券購入でポイントがつくのはかなりありがたいことだ。

そんなこんなで、今のところ、View Suicaよりは、こちらにかなり気持ちが傾いているところ。

*1:決して可愛い女の子のデータが3%の確率で当たる集金システムに課金するわけではない