トップ «前の日(02-11) 最新 次の日(02-13)» 追記   RSS 1.0 FEED  

Journal InTime


2004-02-12 (Thu)

_ プログラミング言語の将来

本日のリンクで気付いたのだが、Yahoo(というかGoogle)で「プログラミング言語の将来」 で検索すると、 C# プログラミング言語の将来の機能 がトップに来るらしい。


2005-02-12 (Sat)

_ 「ツァラトゥストラはかく語りき」ナムコの商標です(予定)

ナムコがゲームの商標として「ツァラトゥストラはかく語りき」を出願してたそうだ。

[スラッシュドット ジャパン | 「ツァラトゥストラはかく語りき」はナムコの商標です(予定)より引用]

岡嶋二人のゲームブックでそんなのなかったっけ。

Tags: その他
本日のツッコミ(全1件) [ツッコミを入れる]

_ サイロス誠 [講談社から出ていた「ツァラトゥストラの翼」ですね。 謎解きに使う暗号が難しすぎて講談社にヘルプの郵便が多数届いたとい..]


2014-02-12 (Wed)

_ 二つのフラグをロックせずに書き換える方法

先日の記事でPR_SET_DUMPABLE周りのLinuxカーネルのコードを読んでいた時に面白いコードがあったのでメモ。

以下のコードは、fs/exec.cのset_dumpable()という関数の定義で、引数のvalueは0(coreダンプしない)・1(coreダンプする)・2(suidセーフにcoreダンプする)という三つの値を取る。

/*
 * set_dumpable converts traditional three-value dumpable to two flags and
 * stores them into mm->flags.  It modifies lower two bits of mm->flags, but
 * these bits are not changed atomically.  So get_dumpable can observe the
 * intermediate state.  To avoid doing unexpected behavior, get get_dumpable
 * return either old dumpable or new one by paying attention to the order of
 * modifying the bits.
 *
 * dumpable |   mm->flags (binary)
 * old  new | initial interim  final
 * ---------+-----------------------
 *  0    1  |   00      01      01
 *  0    2  |   00      10(*)   11
 *  1    0  |   01      00      00
 *  1    2  |   01      11      11
 *  2    0  |   11      10(*)   00
 *  2    1  |   11      11      01
 *
 * (*) get_dumpable regards interim value of 10 as 11.
 */
void set_dumpable(struct mm_struct *mm, int value)
{
	switch (value) {
	case SUID_DUMPABLE_DISABLED:
		clear_bit(MMF_DUMPABLE, &mm->flags);
		smp_wmb();
		clear_bit(MMF_DUMP_SECURELY, &mm->flags);
		break;
	case SUID_DUMPABLE_ENABLED:
		set_bit(MMF_DUMPABLE, &mm->flags);
		smp_wmb();
		clear_bit(MMF_DUMP_SECURELY, &mm->flags);
		break;
	case SUID_DUMPABLE_SAFE:
		set_bit(MMF_DUMP_SECURELY, &mm->flags);
		smp_wmb();
		set_bit(MMF_DUMPABLE, &mm->flags);
		break;
	}
}

コメントにもあるとおり、valueで指定した値は、カーネル内部では独立した二つのフラグで保持されるが、フラグの変更はアトミックに行われないので、中間状態の値を参照してしまう可能性がある。コメントの表でいうと、old→newが0→2、2→0のケースでは、二つのフラグが変更されるため、値の不整合が発生してしまう。

上記のコードでは、この問題を解決するために、フラグ操作の順番を注意深く制御することで、上記のケースでは中間状態が必ず決まった値を取るようにし、その値になっている場合は両方のフラグが立っている状態と見做すことにしている。 具体的には二つもとフラグをクリアする場合はMMF_DUMPABLEからクリアし、二つともフラグをセットする場合はMMF_DUMP_SECURELYからセットすることで、中間状態は必ずMMF_DUMP_SECURITYのみが立っている状態(2進表記で10)になる。

ちなみに上記のsmp_wmb()はメモリへの書き込みを待つためのマクロで、これによって実行順序を保証している(詳しくはがちゃぴん先生の記事参照)。

フラグを参照するget_dumpable()の方では、以下のように値がSUID_DUMPABLE_ENABLED(2進表記で01)より大きければ(つまり10か11なら)、SUID_DUMPABLE_SAFEを返すようになっている。

int __get_dumpable(unsigned long mm_flags)
{
	int ret;

	ret = mm_flags & MMF_DUMPABLE_MASK;
	return (ret > SUID_DUMPABLE_ENABLED) ? SUID_DUMPABLE_SAFE : ret;
}

int get_dumpable(struct mm_struct *mm)
{
	return __get_dumpable(mm->flags);
}
Tags: Linux C

2017-02-12 (Sun)

_ Textbringer 0.1.7

Textbringer 0.1.7をリリースした。変更点は、

  • EditorConfigのサポート。
  • CONFIG[:ambiguos_east_asian_width]を追加。 詳細はREADME参照。
  • Cモードの追加。
  • *Completions*バッファの追加。
  • 複数文字コマンドをエコーエリアに表示。

久々に以下のように長い正規表現を書いた。

TOKEN_REGEXP = /\G(?:
(?<preprocessing_directive>
  ^[ \t\f\v]*(?:\#|%:).*(?:\\\n.*)*[^\\]\n
) |
(?<comment>
  (?<multiline_comment> \/\* (?> (?:.|\n)*? \*\/ ) ) |
  (?<singleline_comment> \/\/ .*(?:\\\n.*)*(?<!\\)\n )
) |
(?<partial_comment>
  (?<multiline_comment> \/\* (?:.|\n)* ) |
  (?<singleline_comment> \/\/ .*? \\\n (?:.|\n)* )
) |
(?<keyword>
  (?:
    auto | break | case | char | const | continue | default | double | do |
    else | enum | extern | float | for | goto | if | inline | int | long |
    register | restrict | return | short | signed | sizeof | static | struct |
    switch | typedef | union | unsigned | void | volatile | while | _Bool |
    _Complex | _Imaginary
  ) \b
) |
(?<constant>
  (?<floating_constant>
    (?<decimal_floating_constant>
      (?<fractional_constant>
        (?<digit_sequence> [0-9]+ )? \. \g<digit_sequence> |
        \g<digit_sequence> \. )
          (?<exponent_part> [eE] [+\-]? \g<digit_sequence> )?
          (?<floating_suffix> [flFL] )?
    ) |
    (?<hexadecimal_floating_constant>
      (?<hexadecimal_prefix> 0x | 0X )
          (?<hexadecimal_fractional_constant>
            (?<hexadecimal_digit_sequence> [0-9a-fA-F]+ )? \.
                \g<hexadecimal_digit_sequence> |
            \g<hexadecimal_digit_sequence> \. )
          (?<binary_exponent_part> [pP] [+\-]? \g<digit_sequence> )
          \g<floating_suffix>? |
      \g<hexadecimal_prefix> \g<hexadecimal_digit_sequence>
          \g<binary_exponent_part> \g<floating_suffix>?
    )
  ) |
  (?<integer_constant>
    (?<decimal_constant> [1-9][0-9]* )
    (?<integer_suffix>
      (?<unsigned_suffix> [uU] ) (?<long_suffix> [lL] )?
      \g<unsigned_suffix> (?<long_long_suffix> ll | LL )?
      \g<long_suffix> \g<unsigned_suffix>?
      \g<long_long_suffix> \g<unsigned_suffix>?
    )? |
    (?<hexadecimal_constant>
      \g<hexadecimal_prefix> \g<hexadecimal_digit_sequence> )
          \g<integer_suffix>? |
    (?<octal_constant> 0 (?<octal_digit> [0-7] )* )
        \g<integer_suffix>?
  ) |
  (?<character_constant>
    ' (?<c_char_sequence>
        (?<c_char>
          [^'\\\r\n] |
          (?<escape_sequence>
            (?<simple_escape_sequence> \\ ['"?\\abfnrtv] ) |
            (?<octal_escape_sequence> \\ \g<octal_digit>{1,3} ) |
            (?<hexadecimal_escape_sequence>
              \\x \g<hexadecimal_digit_sequence> ) |
            (?<universal_character_name>
              \\u[0-9a-fA-F]{4} |
              \\U[0-9a-fA-F]{8} )
          )
        )+
      ) ' |
    L' \g<c_char_sequence> '
  )
) |
(?<string_literal>
  " (?<s_char_sequence>
      (?<s_char> [^"\\\r\n] | \g<escape_sequence> )+ ) " |
  L" \g<s_char_sequence>? "
) |
(?<identifier>
  (?<identifier_nondigit>
    [_a-zA-Z] |
    \g<universal_character_name> )
        (?: \g<identifier_nondigit> | [0-9] )*
) |
(?<punctuator>
  \[   |   \]   |   \(   |   \)   |   \{   |   \}   |
  \.\.\.   |   \.   |
  \+\+   |   \+=   |   \+   |
  ->   |   --   |   -=   |   -   |
  \*=   |   \*   |
  \/=   |   \/   |
  &&   |   &=   |   &   |
  \|\|   |   \|=   |   \|   |
  !=   |   !   |
  ~   |
  ==   |   =   |
  \^=   |   \^   |
  <:   |   <%   |   <<=   |   <<   |   <=   |   <   |
  >>=   |   >>   |   >=   |   >   |
  \?   |   ;   |
  :>   |   :   |
  ,   |
  \#\#   |   \#   |
  %>   |   %:%:   |   %:   |   %=   |   %
) |
(?<space>
  \s+
) |
(?<unknown>.)
    )/x

田中哲スペシャルのおかげでC99のBNFを書き写すだけだと思ったのも束の間、左再帰を避けたり、最左最長マッチに合わせて順番を入れ替えるのが結構大儀であった。

インデントの設定項目は(使ったことのない)xyzzyを参考に以下のようなものを用意した。

CONFIG[:c_indent_level] = 4
CONFIG[:c_indent_tabs_mode] = true
CONFIG[:c_continued_statement_offset] = 4
CONFIG[:c_case_label_offset] = -4
CONFIG[:c_label_offset] = -2

以下のように~/.textbringer.rbに設定するとRubyのソースとだいたい同じスタイルになるはず(バッファローカルの設定はindent_levelとindent_tabs_modeはc_が付かないので注意)。

add_hook :c_mode_hook, -> {
  buf = Buffer.current
  if buf.file_name &&
      File.dirname(buf.file_name).end_with?("/ruby")
    buf[:indent_level] = 4
    buf[:tab_width] = 8
    buf[:indent_tabs_mode] = true
    buf[:c_continued_statement_offset] = 4
    buf[:c_case_label_offset] = -2
    buf[:c_label_offset] = -2
  end
}

K&Rスタイルに対応してないのは仕様である。

_ ストームブリンガー

ストームブリンガー 永遠の戦士エルリック

新訳版で読み進めていたがようやく第4巻の『ストームブリンガー』まで読了した。

第3巻所収の『薔薇の復讐』以外は旧訳で読んでいるはずだったが、記憶以上に呪われている感じだったので、Textbringerを使う時はバックアップに気を付けようと思う。

Tags: