Go言語のflagパッケージを使う

Go言語でコマンドラインオプションを扱う - そこはかとなく書くよん。

に触発されたので、flagパッケージについて自分で使ってみてハマったところを書いておく。

コマンドラインオプションの略称を登録する

flag.IntVar()などのXxxVar()を使う。

これで -boolでも-bでも同じ変数にフラグの結果が反映されるようになる。

$ go run flag_shorthand.go -bool -int 100 -string hoge
bool flag   = true
int flag    = 100
string flag = hoge

$ go run flag_shorthand.go -b -i 100 -s hoge
bool flag   = true
int flag    = 100
string flag = hoge

コマンドラインオプションを最後まで解析する

flag.Parse()の解析は、非フラグ引数(頭に"-"の付いた引数)の前、もしくは"--"の後で打ち切られる。

Flag parsing stops just before the first non-flag argument ("-" is a non-flag argument) or after the terminator "--".

http://golang.org/pkg/flag/#pkg-overview

そのため、以下のようなコマンドラインだとxxxの部分でフラグ解析が打ち切られるため、フラグが設定されない。

$ go run flag_shorthand.go xxx -b -i 100 -s hoge
bool flag   = false
int flag    = 0
string flag = blank

そこで、flag.NewFlagSet()を用いて以下のような処理を書くことでフラグ引数の前にxxxのような非フラグ引数があっても最後までフラグ解析を行わせることができる。

flag.NewFlagSet()でFlagSetを生成した場合、Parse()には解析する文字列のスライスが引数として要求される。その引数の開始インデックスを1ずつ進めてやればいい。

$ go run flag_checkall.go xxx -b -i 100 -s hoge
bool flag   = true
int flag    = 100
string flag = hoge

外部パッケージでoptargなるものがあるそうなので、後で試してみよう。

Go言語は定数配列宣言ができない

以下のコードはコンパイルが通らない。

package main

func main() {
    const array = [...]int {1,2,3,4,5}
}

コンパイルエラー。

const initializer must be constan

Goでは、配列やスライスは全てランタイム中に生成される。 それに対して、定数はコンパイル時に生成される。 そのため、配列を定数として宣言することはできないらしい。

参考

はじめてのOSコードリーディング #2 simhでV6を動かす

simhというエミュレータ上でUNIX V6を動かせるとのことで試してみた。

simhエミュレータのインストール

http://simh.trailing-edge.com/がsimhの開発プロジェクト。

debian系なら apt-get で楽ちんインストール。

$ sudo apt-get install simh

simh用のUNIX V6キットをダウンロード

http://simh.trailing-edge.com/software.htmlからPDP-11 UNIX V6キットをダウンロードする。

$ wget http://simh.trailing-edge.com/kits/uv6swre.zip
$ unzip uv6swre.zip

simhでUNIX V6を動かす

起動の前にPDP-11用の設定ファイルを作る。名前はなんでもいいけど、pdp11.rcにした。

set cpu 11/40
set cpu u18
att rk0 unix0_v6_rk.dsk
att rk1 unix1_v6_rk.dsk
att rk2 unix2_v6_rk.dsk
att rk3 unix3_v6_rk.dsk
boot rk0

simh、UNIX V6を起動する

simhのPDP-11エミュレータを起動する。引数に先ほどの設定ファイルをつける。

$ pdp11 pdp11.rc

PDP-11 simulator V3.8-1
Disabling XQ
@

@の後にunixと入力するとUNIX V6が立ち上がる。ログイン名はroot

@unix
login:root

UNIX V6の終了方法

syncを3回入力してからctrl-eを入力する。

# sync
# sync
# sync
# [ctrl-e]

simhの終了方法

quitを入力

UNIX V6上でアセンブラ出力

  1. ed hoge.cで頑張ってコードを書く
  2. cc -S hoge.cアセンブラコードを吐かせる
  3. cat hoge.sで眺める

参考ページ


2013.1.30追記
ここのページのやり方の方がいいみたい。


はじめてのOSコードリーディング ~UNIX V6で学ぶカーネルのしくみ (Software Design plus)
はじめてのOSコードリーディング ~UNIX V6で学ぶカーネルのしくみ (Software Design plus)

はじめてのOSコードリーディング #1 ことはじめ

UNIXカーネルなどの低レイヤなところに詳しくなりたい。 ずっとそんなことを思っていたので、「はじめてのOSコードリーディング」で勉強を始めた。

はじめてのOSコードリーディング ~UNIX V6で学ぶカーネルのしくみ (Software Design plus)
はじめてのOSコードリーディング ~UNIX V6で学ぶカーネルのしくみ (Software Design plus)

著者の@superhogeさんのブログ↓
「はじめてのOSコードリーディング」という本を出版します - やる気のないはてだ

@7shiさん主催の読書会にも参加してきたので、その内容も含めながら覚え書き。

UNIX V6ソースコードのダウンロード

ここがUNIXの歴史のトップページ。http://minnie.tuhs.org/cgi-bin/utree.pl

ソースコードのアーカイブはここから。http://minnie.tuhs.org/Archive/PDP-11/Distributions/research/Dennis_v6/


第1章: UNIX V6の全体像

カーネルとは?

OSの中核を成す部分。システムを構築するために必要な機能を提供する。

カーネルは、アプリケーションに対してH/Wの抽象化を行い、またシステムコールを提供する。アプリケーションプログラムは、システムコールを使ってカーネルに対して要求を出す。

システム管理機能をカーネルに集約・隠蔽することでセキュリティと保守性を保っている。 また、POSIXという移植性を高めるための規格がある。(Unix TSS 5〜6からPOSIXができてきたらしい)

Pre K&R C

UNIX V6はPre K&R Cで書かれていて、その記法にとてもクセがある。 プロトタイプ宣言なし、キャストなし。

キャストがないのでレジスタ操作は以下の様な無名構造体を用い、1ワードのデータをint型で無理やり読み出し、書き込みする。

PDP-11

UNIX V6を構成するプロセッサ。資料へのリンクを貼っておく。

Vimビルド時のオプション

たぶん2度と思い出せなくなるのでメモ。

$ ./configure --prefix=$HOME/Garage/Toybox/ext --enable-FEATURE \
--enable-mzschemeinterp --enable-perlinterp=yes --enable-pythoninterp=yes \
--enable-python3interp=yes --enable-rubyinterp=yes --enable-cscope \
--enable-multibyte --enable-xim --enable-fontset --with-features=huge \
--enable-gui=no --with-local-dir=$HOME/Garage/Toybox/ext --disable-selinux \
--enable-luainterp=yes

tlibでncursesが必要なので、別途インストールする。 g++入ってないとncursesのビルドに失敗するよ!

$ sudo apt-get install libncurses5-dev libncursesw5-dev


参考