OSDN Git Service

GAST - Gcc Automatically Save Temps
authorTadashi Koike <t-koike@users.sourceforge.jp>
Sat, 17 Oct 2009 17:05:55 +0000 (02:05 +0900)
committerTadashi Koike <t-koike@users.sourceforge.jp>
Sat, 17 Oct 2009 17:05:55 +0000 (02:05 +0900)
README.ja_JP.UTF-8 [new file with mode: 0644]
gast [new file with mode: 0755]
gast_make [new file with mode: 0755]
gast_rpmbuild [new file with mode: 0755]

diff --git a/README.ja_JP.UTF-8 b/README.ja_JP.UTF-8
new file mode 100644 (file)
index 0000000..ee8b5b9
--- /dev/null
@@ -0,0 +1,386 @@
+                            Copyright (C) 2009 Tadashi Koike (T.K)
+目次
+============
+  1. このプロジェクトの目的
+  2. 提供物
+  3. 必要な動作環境
+  4. インストール&セットアップ
+  5. 利用方法
+  6. gast 制御用環境変数
+  7. 役立つ場面(想定)
+  8. このプロジェクトの弱点
+  9. その他
+============
+
+1. このプロジェクトの目的
+
+  このプロジェクト(GAST)は、C言語で作成されたオープンソース製品の
+  コンパイル時に、なんらかの理由により、プリプロセッサで処理された
+  実際のコンパイルにかけられるソースコードも生成物として一緒に入手
+  したいというニーズがある場合、それを支援するための簡易なツールを
+  提供することを目的としたプロジェクトです。
+
+2. 提供物
+  このプロジェクトで提供されるプログラムは、現在のところ以下の3つ
+  です。
+
+  ● gast : gcc コマンドのラッパースクリプト。
+
+      本スクリプトに、シンボリックリンクで gcc や cc などの別名をつ
+      けて、本来のコンパイラよりも先にこのスクリプトが実行プログラム
+      として認識され起動される様に PATH 環境変数を設定して、利用し
+      ます。
+    
+      本スクリプトが起動されると、以下の処理を基本的に実施します。
+
+      1)与えられたコマンド引数を解析し、Cソースファイルのコンパイル
+          であった場合は、与えられたコマンド引数に、-save-temps を
+          追加してコンパイラを起動。
+          Cソースファイルのコンパイルではなかった場合(リンカーとし
+          て呼び出された場合など)は、与えれたコマンド引数そのまま
+          を用いてコンパイラを起動。
+
+      2)Cソースのコンパイルであった場合、プリプロセッサ処理後の
+          ソースファイルが中間ファイルとして生成される(拡張子 .i)。
+          このファイルの退避先ディレクトリが指定されていた場合、
+          そのディレクトリ配下に中間ファイルを移動する。
+
+      3)中間ファイルとしてアセンブラソースファイルも生成されるので
+          それらは不要として削除する。
+
+      なお、これら機能を働かせるには、gast の動作制御用の環境変数を
+      いくつか定義する必要があります。詳細は、「6. gast 制御用環境変数」
+      で記します。
+
+      【注意】
+      コンパイラが make コマンドの配下で実施される場合は、通常の make
+      に代えて、以下に示す gast_make スクリプトの支援を必要とします。
+      これは、通常の make コマンドが、ビルドの効率化のためにコンパイル
+      処理を複数並列で実行する場合があるからです。
+
+      同一のソースコードが、異なるコンパイル処理においてコンパイル対象
+      としてかちあった場合、中間ファイル名が同一であることから、中間
+      ファイルの破壊が発生します。この場合、ビルド処理は失敗します。
+      オープンソース製品のビルド処理を安全に実施するためには、後述の
+      gast_make を利用してください。
+
+
+  ● gast_make : make コマンドのラッパースクリプト。
+
+      本スクリプトに、シンボリックリンクで make や gmake などの別名
+      をつけて、本来の make コマンドよりも先にこのスクリプトが実行
+      プログラムとして認識され起動される様に PATH 環境変数を設定して、
+      利用します。
+    
+      本スクリプトが起動されると、以下の処理を基本的に実施します。
+
+      1)与えられたコマンド引数を解析し、同時に実行できるジョブ数が
+          指定されていた場合(-j<n> または --jobs=<n> オプション)、
+          それを強制的に 1 に変更する。
+          ジョブ数の指定がなされていなかった場合は、与えられたコマンド
+          引数に、-j1 オプションを追加する。
+
+      2)1)で加工されたコマンド引数を用いて、本来の make (or gmake)
+          コマンドを起動する。
+
+
+  ● gast_rpmbuild : rpmbuild コマンドのラッパースクリプト。
+
+      RedHat Enterprise Linux や CentOS, Fedora などの、パッケージを
+      RPM で管理しているシステムでは、バイナリパッケージ(RPM) を
+      ソースパッケージ(SRPM)から作成します。その際に用いられるコマンド
+      が rpmbuild コマンドです。
+
+      本スクリプトに、シンボリックリンクで rpmbuild と別名をつけて、 
+      本来の rpmbuild コマンドよりも先にこのスクリプトが実行プログラム
+      として認識され起動される様に PATH 環境変数を設定して、利用します。
+    
+      本スクリプトが rpmbuild 名で起動されると、以下の処理を行います。
+
+      1)与えられたコマンド引数を解析し、このスクリプト専用のオプション
+          引数である --save-temps-dir オプションが指定されていた場合、
+          それに続く引数を、gast(の別名としての gcc や cc) によって
+          生成されたプリプロセッサ処理済ソースファイル(=中間ファイル)
+          の退避ディレクトリと認識し、動作環境として設定する。
+
+      2)さらに中間ファイルの生成に必要な環境変数を定義する。
+          (PATH環境変数の変更により、ラッパースクリプトが先に認識
+            されるようにするための変更も含む)
+
+      3)--save-temps-dir オプション引数をのぞくコマンドライン引数を
+          伴って、本来の rpmbuild コマンドを実行する。
+
+3. 必要な動作環境
+
+  このスクリプト群が動作するためには、環境として以下のプログラムが
+  必要となります。
+
+    ・gcc コンパイラ(バージョン不問)
+    ・GNU Make コマンド
+    ・bash (ver 3.0以上が望ましい)
+
+  また、以下のコマンドが利用可能であることを強く推奨いたします。
+
+    ・perl(バージョン不問)
+
+      ※存在しない場合、目的のテキストファイルのフィルタリング処理を
+        bash の機能で代替え実行しますが、処理スピードが格段に遅いため
+        (コンパイル時間が通常の 10倍程度かかる)、perl が利用できる
+        環境を用意いただくことを強く推奨します。
+
+4. インストール&セットアップ
+
+  【インストール】
+    本プロジェクトの成果物は、tar + gzip 形式で配布されます。  この
+    ファイルを適当なディレクトリ配下で解凍・展開すると、gast-0.1.0 
+    というディレクトリが作成され、その配下に成果物であるスクリプトが
+    配置されます。  この展開されたことを以って、インストール完了と
+    します(不要となった圧縮ファイルは削除してください)。
+
+    <オペレーション>:以降の例では、/home/foo 配下にインストールすると
+                      仮定します。
+                      プロジェクト成果物は /tmp/gast-0.1.0.tar.gz で
+                      配布されるものと仮定します。
+        $ cd /home/foo
+        $ tar -xvzf /tmp/gast-0.1.0.tar.gz
+        gast-0.1.0/
+        gast-0.1.0/gast
+        gast-0.1.0/gast_make
+        gast-0.1.0/gast_rpmbuild
+        gast-0.1.0/README.ja_JP.UTF-8
+
+  【セットアップ】
+    スクリプトが配置されているディレクトリに移動し、各スクリプトを
+    単独で(オプション引数なしで)実行してください。  各スクリプトは
+    自身の別名となるシンボリックリンクを同一ディレクトリ内に作成しま
+    す。
+
+        $ cd /home/foo/gast-0.1.0
+        $ ./gast
+        gast : Create symbolic link 'gcc'
+        gast : Create symbolic link 'cc'
+
+        $ ./gast_make
+        gast_make : Create symbolic link 'make'
+        gast_make : Create symbolic link 'gmake'
+
+        $ ./gast_rpmbuild
+        gast_rpmbuild : Create symbolic link 'rpmbuild'
+
+  【注意】
+    ・ここで提供されるスクリプト群は、互いが同一ディレクトリに配置
+      されることを想定した動作をします。  よって、個々のスクリプトを
+      単独で別のディレクトリに移動し実行することは、動作に影響します
+      ので避けてください。
+
+    ・ここで提供されるスクリプト群は、本来の make コマンドやコンパイラ
+      自身が配置されているディレクトリ(例:/usr/bin, /usr/local/bin)
+      に配置されることは想定していませんし、本スクリプト群の性格上、
+      禁止です。  できましたら、展開した状態のままお使いください。
+
+    ・当然のことですが、プロダクト全体のビルドにかかる時間は長くなり
+      ます。状況にもよりますが、通常の 1.2〜3倍程度を見積もってくだ
+      さい。
+      
+5. 利用方法
+
+  A)rpmbuil コマンドで SRPM をコンパイルして RPM を作成する場合
+
+    すぐに使いはじめることができます。
+    rpmbuild (=gast_rpmbuild の別名)スクリプトを、直接起動してください。
+
+      例)Linux カーネルの srpm のビルドの際、中間ファイルを抽出する。
+        $ /home/foo/gast-0.1.0/rpmbuild --save-temps-dir /home/foo/tmp \
+          --recompile /tmp/kernel-2.6.18-92.1.10.el5.src.rpm
+
+    オプションの指定方法は、通常の rpmbuild コマンドと変わりません。
+    さらに rpmbuild スクリプトは、--save-temps-dir という独自オプション
+    によって、中間ファイルの退避場所を指定できるようになっています。
+    上記の例では、/home/foo/tmp 配下に退避されます。
+
+    また必要に応じて、GAST_CONTENT_WITHOUT_H, GAST_CONTENT_UNIQUE
+    環境変数を定義して下さい。
+        $ export GAST_CONTENT_WITHOUT_H=
+        $ export GAST_CONTENT_UNIQUE=
+
+    ------------------------------------------------------------------
+    【余談】
+      rpmbuild は通常、ビルド作業を /usr/src/redhat などの、システムが
+      提供する作業ディレクトリで行おうとします。
+      ビルド作業を行うディレクトリを変更する場合は、以下の対処を行う
+      ことで実施できます。
+
+        - ログインディレクトリ配下に、.rpmmacros ファイルを作成する。
+        - .rpmmacros ファイルに、以下のマクロ記述を追加する。
+           %_topdir  <ビルド作業ディレクトリ名>
+
+      設定が正しく反映されているか否かは、以下のコマンドで確認できます。
+           $ rpmbuild --showrc | grep _topdir
+
+      .rpmmacros の記述の仕方は、/usr/lib/macros などの、デフォルトの
+      記述を参考にしてください。
+      以上、CentOS 5 における実績でした。
+    ------------------------------------------------------------------
+
+  B)configure/make/make install タイプのオープンソース・ソフトウェアを
+      ビルドする場合
+
+    以下の手順を実施する必要があります。
+
+      1. gast を制御する環境変数の定義
+      2. 本プロジェクト提供のスクリプト配置ディレクトリを、PATH 環境
+          変数の先頭に追加して、ソフトウェアをビルド
+
+    例)Apache HTTPD 2.2 (httpd-2.2.11.tar.gz) を /tmp 配下に展開して
+        ビルドを行う。
+
+        $ cd /tmp
+        $ tar -xvzf httpd-2.2.11.tar.gz
+        $ cd /tmp/httpd-2.2.11
+        $ ./configure --prefix=/home/foo/local
+                    :
+                    :
+        $ # make の前に、gast 用環境変数の設定
+        $ export GAST_ENABLE=
+        $ export GAST_SOURCE_DIR=/tmp
+        $ export GAST_SAVE_DIR=/home/foo/tmp
+        $ export GAST_CONTENT_WITHOUT_H=
+        $ export GAST_CONTENT_UNIQUE=
+        $
+        $ # ビルド
+        $ PATH=/home/foo/gast-0.1.0:${PATH}  make
+                    :
+                    :
+        $ make install
+
+    【注意】
+        GAST で提供されるスクリプトを、他のビルドツールより
+        優先的に起動するための PATH 環境変数の設定は、export
+        コマンドを用いて固定的に設定してしまうことも可能です。
+        しかし GAST は、作業環境に固定的に組み入れるというよ
+        りは、必要なときに一時的に有効にする、といった用い方
+        の方が、他に影響がなくて好ましいと考えます。 よって、
+        上記のとおり、ビルド作業を行う時だけ GAST の各スクリ
+        プトが有効となるような PATH 変数の指定を行う利用法を
+        推奨します。
+
+    実施し終わったら、上記の環境変数は削除してください。
+        $ unset GAST_ENABLE  GAST_SOURCE_DIR  GAST_SAVE_DIR
+        $ unset GAST_CONTENT_WITHOUT_H GAST_CONTENT_UNIQUE
+
+  C)Cソースファイルを単独でコンパイルする場合
+
+    configure/make と実施することは変わりません。
+
+    また、以下のような実施方法もあります(コマンド列が長くて面倒ですが)。
+
+        $ GAST_ENABLE= GAST_SOURCE_DIR=/tmp GAST_SAVE_DIR=/home/foo/tmp \
+        > GAST_CONTENT_WITHOUT_H=  PATH=/home/foo/gast-0.1.0:$PATH \
+        > gcc test.c
+
+    いろいろ使ってみてください。
+
+6. gast 制御用環境変数
+
+    gast (gcc ラッパースクリプト) が中間ファイルを生成し退避する動作は、
+    いくつかの環境変数の設定に基づいて行われます。  gast を用いる場合は
+    あらかじめこれら環境変数の設定をおこなってください。
+
+    GAST_ENABLE
+      この環境変数が存在する場合(かつ値が "no" でない場合)、gast は
+      gast から起動される本来のコンパイラに、中間ファイルの生成を指示
+      するオプションを付与してコンパイルを実施します。
+      もしこの環境変数が存在しない場合には、gast は、通常のコンパイラ
+      による起動とまったく同じ振舞いをします(=中間ファイルは作成され
+      ない)。
+
+    GAST_SAVE_DIR=<DIR>
+      この環境変数が存在する場合でかつ、その値がディレクトリ名であった
+      場合(この時点では存在していなくても良い)、生成された中間ファイル
+      は、この指定されたディレクトリに退避されます。
+      指定されたディレクトリが存在しなかった場合には、ディレクトリは
+      スクリプトによって作成が試みられます。
+
+      【注意】
+      この環境変数が存在しなかった場合、中間ファイルはコンパイル実行時
+      のカレントディレクトリに配置されたままとなりますが、名前だけは、
+      以下の様に変更されます。
+
+        例)test.i ---> test.0.i
+
+      これは、同一のソースコードが条件を変えて複数回コンパイルされた
+      場合に、古い中間ファイルが上書きされて無くなってしまうことを
+      防ぐための措置です。予めご了承ください。
+
+    GAST_SOURCE_DIR=<DIR>
+      この環境変数が存在する場合でかつ、その値がディレクトリ名であった
+      場合、コンパイル対象Cソースファイルの完全パス名からこのディレク
+      トリ名が除去された相対パス名が、中間ファイルを退避する際のパス名
+      に反映されます。
+      この環境変数が存在しない場合は、Cソースファイルのルート "/" から
+      の相対パスを取得して、退避ディレクトリ配下に反映されます。
+
+    GAST_CONTENT_WITHOUT_H
+      この環境変数が存在する場合(かつ値が "no" でない場合)、退避される
+      中間ファイルの内容はスリム化されます。
+      具体的には、プリプロセッサ処理済ソースファイルの中から、ヘッダー
+      ファイルが展開された箇所は取り除き(*1)、本来のCソースファイル部分の
+      展開結果のみが残るように保存する動作を行います。
+
+        (*1):ただし、ヘッダーファイルのインクルードの痕跡は残すように
+              しています。どんなヘッダファイルが関与したかは判ります。
+
+    GAST_CONTENT_UNIQUE
+      通常の動作では、同一のCソースファイルがコンパイルオプションを
+      変えて何度もコンパイルがなされる場合、その各々で生成される中間
+      ファイルを、(簡易番号を付けて)その都度退避します。
+      この環境変数が存在する場合(かつ値が "no" でない場合)、異なる
+      コンパイルオプションで何度かコンパイルが行われた場合、生成される
+      中間ファイルの内容が、以前に作成されている中間ファイルの内容と
+      結果として一緒であれば、そのとき生成された中間ファイルは退避されず
+      破棄され、同一の内容が重複して退避されないようになります。
+      
+      ※その代わり、コンパイルオプションの記録は完全には辿れなくなります。
+        
+
+7. 役立つ場面(想定)
+
+  1)ソースコード解析の補助として(マクロの展開結果を手軽に知りたい)。
+
+      マクロで定義される定数が、各OS/アーキテクチャ毎で異なって定義
+      されていて、それら定義が複雑である場合、実際のマクロが展開され
+      た結果がどのようになるのか、ソースコードの解読ではすぐには解か
+      らない。
+        →プリプロセッサ処理後のソースを見てみたい。
+        →GAST 環境配下でビルド処理を実施し、入手してみる。
+
+  2)ソースコードからエラーメッセージを収集するための解析対象として。
+
+      エラーメッセージの出力関数(syslog関数や printf関数、Linux
+      カーネルならば printk関数など)で出力されるメッセージを収集
+      したいが、それらがヘッダーファイル内でマクロ定義によりラップ
+      されてしまった場合、ソースコード上にはエラーメッセージ出力関数
+      は表れず、メッセージ収集から洩れる場合がある。
+
+        →マクロ展開済のソースコードなら、エラーメッセージ出力関数
+          が展開されているので、そこから収集すれば洩れがないだろう。
+        →マクロ展開済み(=プリプロセッサ処理後)のソースを入手したい。
+        →GAST 環境配下で、ビルド処理を実施し、入手してみる。
+
+8. このプロジェクトの弱点
+
+  C言語で作成されたオープンソース製品のビルドに際して、用いるコンパイラ
+  のパスが、もしフルパスで指定されていた場合は、gast が介在できる余地
+  がないため、中間ファイルを取得することができません。悪しからず。
+
+9. その他
+
+  GAST 環境でもしオープンソース製品のビルドに失敗した場合、まずは、GAST
+  環境ではない状態で再度ビルドを試みてください。 もしそこでビルドが同じ
+  く失敗する場合は、GAST 環境の影響ではない、といえます。 逆に、GAST 
+  環境でない状態ではビルドが成功する場合には、GAST 提供のプログラム(主に
+  gast スクリプト)にバグがある場合が示唆されます。ビルドエラー時には、
+  このような事象の切り分けを行ってください。
+
+以上
+
diff --git a/gast b/gast
new file mode 100755 (executable)
index 0000000..2f6d29d
--- /dev/null
+++ b/gast
@@ -0,0 +1,563 @@
+#!/bin/bash
+#   gast (Gcc Automatically -Save-Temps) : wrapper script for gcc to save temporary file.
+#
+#   Copyright (C) 2009 Tadashi Koike
+#
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program; if not, write to the Free Software
+#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
+#   02110-1301, USA.
+#
+#----------------------------------------------------------------------
+# (I am weak in English. Please modify English comment more suitable. :T.K)
+#
+# [ Explanation of environment variable ]
+#  - GAST_ENABLE
+#        When this environment variable is defined (however excludes its 
+#        value is "no"), this script works to generate compiler's temporary
+#        file (.i file) automatically, and stores it.
+#        When this environment variable is not defined, this script behaves
+#        itself like just same as an original gcompiler binary.
+#
+#  - GAST_SAVE_DIR
+#        When this environment variable is defined and its value can be
+#        recognized a directory name, a genrerated temporary file (.i file)
+#        by compiler is moved to that directory.
+#        When that directory is not defined , this script attempt to create 
+#        that directory.
+#
+#  - GAST_SOURCE_DIR
+#        When this environment variable is defined and its value can be 
+#        recognized a directory name, this script tries to get a relative 
+#        path-name from a source file path-name by removing a directory 
+#        name which this environment means. And that relative path-name 
+#        applies under the GAST_SAVE_DIR directory to moved a temporary 
+#        file (.i file).
+#        When this environment variable is not defined or the value does
+#        not match a header of source file path-name, this script get a 
+#        relative path-name by removing "/" from a top of source file 
+#        path-name.
+#
+#        ** NOTE **
+#        When this environment variable is not defined but this script 
+#        is executed under a build process by 'rpmbuild' command, this 
+#        script sets this environment variable automatically with a
+#        value of RPM_BUILD_DIR.
+#
+#  - GAST_CONTENT_WITHOUT_H
+#        When this environment variable is defined (however excludes its 
+#        value is "no"), created temporary file (.i file) is modified to
+#        remove contents which are expanded from header files, and stored
+#        as a substitute for an original temporary file (.i file).
+#
+#  - GAST_CONTENT_UNIQUE
+#        By default, when a C source file is compiled repeatedly with 
+#        different compile options each time, this script store each 
+#        temporary files.
+#        When this environment variable is defined (however excludes its
+#        value is "no"), If compile options are different but content of
+#        temporary file is same as one of some previous stored files, 
+#        this script does not store temporary file at this time.
+
+VERSION="0.1.0"
+ORIGINAL_NAME="gast"
+CWD=`pwd`
+SCRIPT_NAME=${0##*/}
+SCRIPT_PATH=${0%/*}
+
+WORK_DIR="/tmp"
+
+# If this script is executed under the rpmbuild command, GAST_SOURCE_DIR is
+# forced to set value by RPM_BUILD_DIR environment variable's one.
+[ -n "${RPM_BUILD_DIR}" ] && GAST_SOURCE_DIR="${RPM_BUILD_DIR}"
+[ -n "${GAST_SOURCE_DIR}" ] && GAST_SOURCE_DIR=${GAST_SOURCE_DIR%/}
+
+# When this script is executed as 'gast', this script creates symbolic link
+# file name as compiler alias name and exit.
+if [ "${SCRIPT_NAME}" = "${ORIGINAL_NAME}" ]; then
+    for arg in "$@"
+    do
+        case "${arg}" in
+        '--version'|'-v')
+            echo "${ORIGINAL_NAME} ${VERSION}"
+            exit 0
+            ;;
+        '--help'|'-h')
+            cat <<EOL
+usage : ${ORIGINAL_NAME} [-v|--version] [-h|--help]
+
+  -h, --help              display this help and exit
+  -v, --version           display version information and exit
+
+  When this script is executed as '${ORIGINAL_NAME}' with no option, this script 
+  creates symbolic link toward itself which name is from compiler (e.g. gcc/cc).
+
+  When this script is executed as compiler, this script executes original 
+  compiler with additional -save-temps option (If GAST_ENABLE is defined), and
+  stores temporary files.
+
+[ environment variables to control storing temporary files ]
+    GAST_ENABLE              : add '-save-temps' option automatically
+                               in compiling when this variable is defined.
+    GAST_SAVE_DIR=<DIR>      : directory name temporary file is stored in.
+    GAST_SOURCE_DIR=<DIR>    : top directory of source tree.
+    GAST_CONTENT_WITHOUT_H : slim temporary files when this variable 
+                               is defined.
+EOL
+            exit 0
+            ;;
+        *)
+            echo "usage : ${ORIGINAL_NAME} [--version|-v] [--help|-h]"
+            exit 1
+            ;;
+        esac
+    done
+
+    cd "${SCRIPT_PATH}"
+    for cmd in gcc cc
+    do
+        if [ -e "${cmd}" ]; then
+            file "${cmd}" 2>/dev/null | egrep 'symbolic link' >/dev/null 2>&1
+            if [ "$?" -ne 0 ]; then
+                echo "${ORIGINAL_NAME} : '${cmd}' exists as normal file or directory. Could not create symbolic link." >&2
+                continue
+            fi
+        fi
+        ln -sf "${ORIGINAL_NAME}" "${cmd}"
+        if [ "$?" -eq 0 ]; then
+            echo "${ORIGINAL_NAME} : Create symbolic link '${cmd}'" >&2
+        else
+            echo "${ORIGINAL_NAME} : Couldn't create symbolic link '${cmd}'" >&2
+        fi
+    done
+    exit 0
+fi
+
+# get a directory path (full-path) of this script
+case "${SCRIPT_PATH}" in
+    '.')       SCRIPT_PATH="${CWD}" ;;
+    \./*)      SCRIPT_PATH="${CWD}/${SCRIPT_PATH#*/}" ;;
+    '~')       SCRIPT_PATH="${HOME}" ;;
+    \~/*)      SCRIPT_PATH="${HOME}/${SCRIPT_PATH#*/}" ;;
+    \/*)               :       ;;
+    *)         SCRIPT_PATH="${CWD}/${SCRIPT_PATH}" ;;
+esac
+
+# leaves out a script path name from PATH environment variable because of
+# executing original compiler binary file in this script.
+path_tmp=
+for dir in ${PATH//:/ }
+do
+    [ "${dir}" = "${SCRIPT_PATH}" ] && continue
+    [ "${dir}" = '.' ] && dir="${CWD}"
+
+    if [ -z "${path_tmp}" ]; then
+        path_tmp="${dir}"
+    else
+        path_tmp="${path_tmp}:${dir}"
+    fi
+done
+export PATH=${path_tmp}
+unset path_tmp
+
+# When GAST_ENABLE does't exist, execute an original compiler and exit.
+if [ "${GAST_ENABLE=no}" = "no" ]; then
+    exec "${SCRIPT_NAME}" "$@"
+fi
+
+# Check whether C source file(s) is/are specified.
+# And create new commandline arguments.
+asm_notdelete_flg=
+pipe_flg=
+idx=0
+idx_src=0
+for arg in "$@"
+do
+    new_args[$idx]="${arg}"
+
+    case "${arg}" in
+    *.c)       src_list[$idx_src]="${arg}"
+                let idx_src+=1
+       ;;
+    '-S')      asm_notdelete_flg="YES"
+       ;;
+    '-pipe')   pipe_flg="YES"
+                new_args[$idx]="-save-temps"
+       ;;
+    esac
+    let idx+=1
+done
+
+# Compiling
+if [ -z "${src_list[*]}" ]; then
+    # No C source file was specified. -save-temps option does not need.
+    exec "${SCRIPT_NAME}" "$@"
+else
+    # C source file(s) is/are specified. -save-temp option is set to argument.
+    if [ -z "${pipe_flg}" ]; then
+        "${SCRIPT_NAME}" -save-temps "$@"
+    else
+        "${SCRIPT_NAME}" "${new_args[@]}"
+    fi
+    RET=$?
+fi
+
+
+# modify a value of  GAST_SOURCE_DIR environment variable to full-path name.
+# When GAST_SOURCE_DIR doesn't exist, define it and set null.
+case "${GAST_SOURCE_DIR}" in
+    '')                GAST_SOURCE_DIR="/" ;;
+    '.')       GAST_SOURCE_DIR="${CWD}" ;;
+    \./*)      GAST_SOURCE_DIR="${CWD}/${GAST_SOURCE_DIR#*/}" ;;
+    '~')       GAST_SOURCE_DIR="${HOME}" ;;
+    \~/*)      GAST_SOURCE_DIR="${HOME}/${GAST_SOURCE_DIR#*/}" ;;
+    \/*)               :       ;;
+    *) GAST_SOURCE_DIR="${CWD}/${GAST_SOURCE_DIR}" ;;
+esac
+GAST_SOURCE_DIR="${GAST_SOURCE_DIR%/}"
+# NOTE : In above process, when user set GAST_SOURCE_DIR as "/" or
+#         GAST_SOURCE_DIR doesn't exists, value of GAST_SOURCE_DIR is set to "".
+
+# When GAST_CONTENT_WITHOUT_H environment variable exist, define a filter 
+# function.
+HAS_PERL=`which perl 2>/dev/null`
+
+if [ "${GAST_CONTENT_WITHOUT_H=no}" != "no" ]; then
+    if [ -n "${HAS_PERL}" ]; then
+        function filter_tempfile_perl () {
+            perl -e '
+#----------(start temporary perl script)-------------------------
+BEGIN {
+  $prnt_flg=-1;
+  $fname="'$1'";
+}
+while (<>) {
+  if (/^#\s+(\d+)\s+"([^"]+)".*$/) {
+      $line_no = $1;
+      $cfile = $2;
+      $cfile =~ s{^.*/}{};
+      if ($cfile eq $fname) {
+          print;
+          $prnt_flg = $line_no if ($prnt_flg >= 0);
+      } elsif ($cfile =~ /^</) {
+          print;
+          $prnt_flg = 0  if ($cfile eq "<built-in>");
+      } else {
+          if  ($prnt_flg == -1) {
+              print;
+          } elsif  ($line_no == 1) {
+              print;
+              $prnt_flg = 0 if ($prnt_flg >= 0);
+          } else {
+              $prnt_flg = 0;
+          }
+      }
+  } elsif ($prnt_flg > 0) {
+      print;
+  }
+}
+#----------(end temporary perl script)---------------------------
+'
+        }
+
+        function delete_added_info_perl () {
+            perl -e '
+#----------(start temporary perl script)-------------------------
+BEGIN {
+  $prnt_flg=0;
+}
+while (<>) {
+  if ($prnt_flg != 0) {
+      print;
+  } elsif (/^#\s+(\d+)\s+"<compile options>/) {
+      $prnt_flg=1;
+  }
+}
+#----------(end temporary perl script)---------------------------
+'
+        }
+
+    elif [ ${BASH_VERSION%%.*} -ge 3 ]; then
+        function filter_tempfile_bash () {
+            prnt_flg=-1
+            fname="$1"
+            IFS_SAVE=$IFS
+            IFS=
+            while read line
+            do
+                if [[ "${line}" =~ "^#[ \t]+([0-9]+)[ \t]+\"([^\"]+)\".*$" ]]; then
+                    line_no=${BASH_REMATCH[1]}
+                    cfile=${BASH_REMATCH[2]}
+                    cfile=${cfile##*/}
+                    #echo "$line_no : $cfile"
+                    if [ "${cfile}" = "${fname}" ]; then
+                        echo "${line}"
+                        [ "${prnt_flg}" -ge 0 ] && prnt_flg="${line_no}"
+                    elif [ "${cfile:0:1}" = "<" ]; then
+                        echo "${line}"
+                        [ "${cfile}" = "<built-in>" ] && prnt_flg=0
+                    else
+                        if [ "${prnt_flg}" -eq -1 ]; then
+                            echo "${line}"
+                        elif [ "${line_no}" -eq 1 ]; then
+                            echo "${line}"
+                            [ "${prnt_flg}" -ge 0 ] && prnt_flg=0
+                        else
+                            prnt_flg=0
+                        fi
+                    fi
+                else
+                    [ "${prnt_flg}" -gt 0 ] && echo "${line}"
+                fi
+            done
+            IFS=$IFS_SAVE
+        }
+
+        function delete_added_info_bash () {
+            prnt_flg=0
+            IFS_SAVE=$IFS
+            IFS=
+            while read line
+            do
+                if [ "${prnt_flg}" -ne 0 ]; then
+                    echo "${line}"
+                elif [[ "${line}" =~ "^#[ \t]+[0-9]+[ \t]+\"<compile options" ]]; then
+                    prnt_flg=1
+                fi
+            done
+            IFS=$IFS_SAVE
+        }
+    fi
+fi
+
+# processes the compiler's temporary file
+for src_file in "${src_list[@]}"
+do
+    # get full-path name of a C source file.
+    fullname=
+    case "${src_file}" in
+    \/*)       fullname="${src_file}" ;;
+    \~/*)      fullname="${HOME}/${src_file#*/}" ;;
+    \./*)      fullname="${CWD}/${src_file#*/}" ;;
+    *)         fullname="${CWD}/${src_file}" ;;
+    esac
+
+    # Get relative-path of C source file from GAST_SOURCE_DIR directory.
+    basename="${fullname##*/}" # C source filename
+    dirname="${fullname%/*}"   # directory name of C source file (full-path)
+    target="${basename/%.c/.i}"        # Compiler's temporary filename (.i file)
+    asmfile="${basename/%.c/.s}"       # Compiler's temporary filename (.s file)
+    src_relative_dir=          # directory name of C source file (relative-path from GAST_SOURCE_DIR)
+
+    case "${fullname}" in
+    ${GAST_SOURCE_DIR}/*)      # contain GAST_SOURCE_DIR=""
+        if [ "${dirname}" = "${GAST_SOURCE_DIR}" ]; then
+            src_relative_dir="."
+        else
+            src_relative_dir="${dirname#${GAST_SOURCE_DIR}/}"
+        fi
+        ;;
+    *)
+        # source file is not under the GAST_SOURCE_DIR directory.
+        # Set the relative-path from '/' directory.
+        src_relative_dir="${dirname#/}"
+        ;;
+    esac
+    [ "${src_relative_dir:0:1}" = '/' ] && src_relative_dir="${src_relative_dir#/}"
+    # Delete assembler temporary file (except that compiler is executed with -S option)
+    [ -e "${asmfile}" -a -z "${asm_notdelete_flg}" ] && rm -f "${asmfile}" > /dev/null 2>&1
+
+    if [ -e "${target}" ]; then
+        if [ "${target}" = "conftest.i" ]; then
+            # temporary file is created by 'configure' script as test.
+            rm -f "${target}"
+            continue
+        fi
+
+        # Add an information in the header of temporary file.
+        # When filtering temporary file was specified, try it.
+        tmpfile_org=
+        until [ -n "${tmpfile_org}" -a ! -e "${tmpfile_org}" ]
+        do
+            tmpfile_org="${target}.${RANDOM}${RANDOM}${RANDOM}"
+        done
+        trap "rm -rf ${tmpfile_org} ${target} 2>/dev/null" HUP INT QUIT ABRT TERM XCPU
+
+        mv "${target}" "${tmpfile_org}"
+        if [ $? -eq 0 ]; then
+            echo "# 1 \"<compile options> $@\"" > "${target}"
+            #if [ -z "${pipe_flg}" ]; then
+            #    echo "# 1 \"<modified compile options> -save-temps $@\"" >> "${target}"
+            #else
+            #    echo "# 1 \"<modified compile options> ${new_args[@]}\"" >> "${target}"
+            #fi
+
+            if [ "${GAST_CONTENT_WITHOUT_H=no}" = "no" ]; then
+                cat "${tmpfile_org}" >> "${target}"
+            else
+                #echo "# 1 \"<GAST_CONTENT_WITHOUT_H>\"" >> "${target}"
+                if [ -n "${HAS_PERL}" ]; then
+                    filter_tempfile_perl "${basename}" < "${tmpfile_org}" >> "${target}"
+                elif [ ${BASH_VERSION%%.*} -ge 3 ]; then
+                    filter_tempfile_bash "${basename}" < "${tmpfile_org}" >> "${target}"
+                else
+                    cat "${tmpfile_org}" >> "${target}"
+                fi
+            fi
+        fi
+
+        # Check whether the GAST_SAVE_DIR has a value or not.
+        # When it has a value, that is recognized as a directory name.
+        # When such directory does not exist, try to create.
+        if [ -n "${GAST_SAVE_DIR}" ]; then
+            GAST_SAVE_DIR="${GAST_SAVE_DIR%/}"
+            if [ ! -d "${GAST_SAVE_DIR}" ]; then
+                if [ -e "${GAST_SAVE_DIR}" ]; then
+                    echo "${ORIGINAL_NAME} : ${GAST_SAVE_DIR} is not a directory." >&2
+                    GAST_SAVE_DIR=
+                else
+                    mkdir -p "${GAST_SAVE_DIR}"
+                    if [ $? -ne 0 ]; then
+                        echo "${ORIGINAL_NAME} : Couldn't create ${GAST_SAVE_DIR} directory." >&2
+                        GAST_SAVE_DIR=
+                    fi
+                fi
+            fi
+        fi
+
+        # define a directory path-name of temporary file to resotre.
+        temp_dirname=
+        if [ -n "${GAST_SAVE_DIR}" ]; then
+            # resolve a directory path-name of a temporary file to move.
+
+            if [ "${src_relative_dir}" = "." ]; then
+                temp_dirname="${GAST_SAVE_DIR}"
+            else
+                temp_dirname="${GAST_SAVE_DIR}/${src_relative_dir}"
+            fi
+
+            # Check a directory to move a temporary file.
+            if [ -e "${temp_dirname}" ]; then
+                if [ ! -d "${temp_dirname}" ]; then
+                    echo "${ORIGINAL_NAME}(${SCRIPT_NAME}): ${temp_dirname} is not a directory. Couldn't move ${target} to ${temp_dirname} ." >&2
+                    temp_dirname=
+                fi
+            else
+                # create a directory
+                mkdir -p ${temp_dirname}
+                if [ $? -ne 0 ]; then
+                    echo "${ORIGINAL_NAME}(${SCRIPT_NAME}): Couldn't create ${temp_dirname} directory, so couldn't move ${target} to ${temp_dirname} ." >&2
+                    temp_dirname=
+                fi
+            fi
+        else
+            temp_dirname=
+        fi
+
+        # set destination filename(full-path) to move a temporary file.
+        loop_count=0
+        skip_moving=
+        dest_name=
+        dest_file=
+        if [ -n "${temp_dirname}" ]; then
+            dest_name=${target}
+            dest_file="${temp_dirname}/${dest_name}"
+        else
+            # When destination directory to store the temporary file doesn't
+            # exist, try to rename temporary file as '*****.0.i', because
+            # if some C source file is compiled over and over, old temporary
+            # file is overwrited by new one. We wish to avoid that.
+            dest_name="${target/%.i/.${loop_count}.i}"
+            dest_file="${dest_name}"
+        fi
+
+        while [ -e "${dest_file}" ]
+        do
+            let loop_count+=1
+            # software loop limit
+            if [ "${loop_count}" -ge 500 ]; then
+                echo "${ORIGINAL_NAME}(${SCRIPT_NAME}): loop abort.  give up to move ${target} to ${temp_dirname} ." >&2
+                skip_moving="YES"
+                break
+            fi
+
+            # destination file already exists. compare a content.
+            cmp_result=
+            if [ "${GAST_CONTENT_UNIQUE=no}" != "no" ]; then
+                # comparison excluding "<compile option>" line.
+                tmpfile_prev=
+                until [ -n "${tmpfile_prev}" -a ! -e "${tmpfile_prev}" ]
+                do
+                    tmpfile_prev="${WORK_DIR}/${destname}.${RANDOM}${RANDOM}${RANDOM}"
+                    tmpfile_cur="${WORK_DIR}/${target}.${RANDOM}${RANDOM}${RANDOM}"
+                    trap "rm -rf ${tmpfile_prev} ${tmpfile_cur} 2>/dev/null" HUP INT QUIT ABRT TERM XCPU
+                done
+
+                if [ -n "${HAS_PERL}" ]; then
+                    delete_added_info_perl < "${dest_file}" > "${tmpfile_prev}"
+                    delete_added_info_perl < "${target}" > "${tmpfile_cur}"
+                elif [ ${BASH_VERSION%%.*} -ge 3 ]; then
+                    delete_added_info_bash < "${dest_file}" > "${tmpfile_prev}"
+                    delete_added_info_bash < "${target}" > "${tmpfile_cur}"
+                fi
+                if [ -e "${tmpfile_prev}" -a -e "${tmpfile_cur}" ]; then
+                    diff --brief "${tmpfile_prev}" "${tmpfile_cur}" > /dev/null 2>&1
+                    cmp_result=$?
+                else
+                    # failed to compare. 
+                    cmp_result=1
+                fi
+                rm -f "${tmpfile_prev}" "${tmpfile_cur}" > /dev/null 2>&1
+                trap - HUP INT QUIT ABRT TERM XCPU
+            else
+                # comparison including "<compile option>" line.
+                diff --brief "${dest_file}" ${target} > /dev/null 2>&1
+                cmp_result=$?
+            fi
+
+            if [ "${cmp_result}" -eq 0 ]; then
+                # delete current temporary file.
+                inode_from=`ls -i "${target}" | sed -e 's/\([0-9][0-9]*\)[^0-9]*/\1/'`
+                inode_to=`ls -i "${dest_file}" | sed -e 's/\([0-9][0-9]*\)[^0-9]*/\1/'`
+                [ "${inode_from}" != "${inode_to}" ] && rm -f "${target}"
+
+                skip_moving="YES"
+                break
+            else
+                # same file already exists and contents is different.
+                # try to store this temporary file with another filename
+                # by using ${loop_count} number.
+                dest_name="${target/%.i/.${loop_count}.i}"
+                if [ -n "${temp_dirname}" ]; then
+                    dest_file="${temp_dirname}/${dest_name}"
+                else
+                    dest_file="${dest_name}"
+                fi
+            fi
+        done
+
+        # move a temporary file to a save-directory.
+        if [ -z "${skip_moving}" ]; then
+            mv -f "${target}" "${dest_file}" 2>/dev/null
+            [ $? -ne 0 ] && echo "${ORIGINAL_NAME}(${SCRIPT_NAME}): Couldn't move ${target} to ${dest_file} ." >&2
+        fi
+
+        # Delete original temporary file.
+        rm -f "${tmpfile_org}"
+        trap - HUP INT QUIT ABRT TERM XCPU
+
+    fi #if [ -e "${target}" ]; then
+done
+
+# return with compiler's return code
+exit "${RET}"
diff --git a/gast_make b/gast_make
new file mode 100755 (executable)
index 0000000..bf0b542
--- /dev/null
+++ b/gast_make
@@ -0,0 +1,172 @@
+#!/bin/bash
+#   gast_make : wrapper script for gmake command to execute with -j1 option
+#
+#   Copyright (C) 2009 Tadashi Koike
+#
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program; if not, write to the Free Software
+#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
+#   02110-1301, USA.
+#
+#----------------------------------------------------------------------
+# (I am weak in English. Please modify English comment more suitable. :T.K)
+
+VERSION=0.1.0
+ORIGINAL_NAME="gast_make"
+CWD=`pwd`
+SCRIPT_NAME=${0##*/}
+SCRIPT_PATH=${0%/*}
+
+# check wheter perl can use or not.
+HAS_PERL=`which perl 2>/dev/null`
+
+# When this script is executed as 'gast', this script creates symbolic link
+# file name as compiler alias name and exit.
+if [ "${SCRIPT_NAME}" = "${ORIGINAL_NAME}" ]; then
+    for arg in "$@"
+    do
+        case "${arg}" in
+        '--version'|'-v')
+            echo "${ORIGINAL_NAME} ${VERSION}"
+            exit 0
+            ;;
+        '--help'|'-h')
+            cat <<EOL
+usage : ${ORIGINAL_NAME} [-v|--version] [-h|--help]
+
+  -h, --help              display this help and exit
+  -v, --version           display version information and exit
+
+  When this script is executed as '${ORIGINAL_NAME}' with no option, this script 
+  creates symbolic link toward itself which name is from make-command (e.g. 
+  make/gmake).
+
+  When this script is executed as make command, this script executes original
+  command with additional -j1 option (to avoid compiling parallel) .
+EOL
+            exit 0
+            ;;
+        *)
+            echo "usage : ${ORIGINAL_NAME} [--version|-v] [--help|-h]"
+            exit 1
+            ;;
+        esac
+    done
+
+    cd "${SCRIPT_PATH}"
+    for cmd in make gmake
+    do
+        if [ -e "${cmd}" ]; then
+            file "${cmd}" 2>/dev/null | egrep 'symbolic link' >/dev/null 2>&1
+            if [ "$?" -ne 0 ]; then
+                echo "${ORIGINAL_NAME} : '${cmd}' exists as normal file or directory. Could not create symbolic link." >&2
+                continue
+            fi
+        fi
+        ln -sf "${ORIGINAL_NAME}" "${cmd}"
+        if [ "$?" -eq 0 ]; then
+            echo "${ORIGINAL_NAME} : Create symbolic link '${cmd}'" >&2
+        else
+            echo "${ORIGINAL_NAME} : Couldn't create symbolic link '${cmd}'" >&2
+        fi
+    done
+    exit 0
+fi
+
+# get a directory path (full-path) of this script
+case "${SCRIPT_PATH}" in
+    '.')       SCRIPT_PATH="${CWD}" ;;
+    \./*)      SCRIPT_PATH="${CWD}/${SCRIPT_PATH#*/}" ;;
+    '~')       SCRIPT_PATH="${HOME}" ;;
+    \~/*)      SCRIPT_PATH="${HOME}/${SCRIPT_PATH#*/}" ;;
+    \/*)               :       ;;
+    *)         SCRIPT_PATH="${CWD}/${SCRIPT_PATH}" ;;
+esac
+
+# Get an original make command.
+path_save="${PATH}"
+path_tmp=
+has_tool_path=
+
+for dir in ${PATH//:/ }
+do
+    if [ "${dir}" = "${SCRIPT_PATH}" ]; then
+        has_tool_path="yes"
+        continue
+    fi
+    [ "${dir}" = '.' ] && dir="${CWD}"
+
+    if [ -z "${path_tmp}" ]; then
+        path_tmp="${dir}"
+    else
+        path_tmp="${path_tmp}:${dir}"
+    fi
+done
+export PATH=${path_tmp}
+unset path_tmp
+
+MAKE_BIN=`which "${SCRIPT_NAME}" 2>/dev/null`
+if [ -z "${MAKE_BIN}" ]; then
+    echo "${ORIGINAL_NAME} : Couldn't find original ${SCRIPT_NAME} command. exit." >&2
+    exit 1
+fi
+
+# recover PATH environment variable
+if [ -n "${has_tool_path}" ]; then
+    export PATH="${path_save}"
+else
+    export PATH="${SCRIPT_PATH}:${path_save}"
+fi
+unset path_save has_tool_path
+
+# Check arguments to modify -j option
+next_is_jobs_flg=
+has_j_option=
+idx=0
+for arg in "$@"
+do
+    new_args[$idx]="${arg}"
+
+    if [ -n "${next_is_jobs_flg}" ]; then
+        next_is_jobs_flg=
+        case "${arg}" in
+            -*)        :
+                ;;
+            *) new_args[$idx]="1"
+                ;;
+        esac
+    else
+        # modify -j/--jobs option
+        case "${arg}" in
+            '-j')      next_is_jobs_flg="yes"
+                        has_j_option="yes"
+                ;;
+            \-j*)      new_args[$idx]="-j1"
+                        has_j_option="yes"
+                ;;
+            \-\-jobs*) new_args[$idx]="--jobs=1"
+                        has_j_option="yes"
+                ;;
+        esac
+    fi
+    let idx+=1
+done
+
+# execute make command with -j1 option
+if [ -n "${has_j_option}" ]; then
+    #echo "${MAKE_BIN} ${new_args[@]}" >&2
+    exec "${MAKE_BIN}" "${new_args[@]}"
+else
+    #echo "${MAKE_BIN} -j1 $@" >&2
+    exec "${MAKE_BIN}" -j1 "$@"
+fi
diff --git a/gast_rpmbuild b/gast_rpmbuild
new file mode 100755 (executable)
index 0000000..93adc80
--- /dev/null
@@ -0,0 +1,146 @@
+#!/bin/bash
+#   gast_rpmbuild : wrapper script for rpmbuild command to set environment using gast
+#
+#   Copyright (C) 2009 Tadashi Koike
+#
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program; if not, write to the Free Software
+#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
+#   02110-1301, USA.
+#
+#----------------------------------------------------------------------
+# (I am weak in English. Please modify English comment more suitable. :T.K)
+
+VERSION=0.1.0
+ORIGINAL_NAME="gast_rpmbuild"
+SCRIPT_NAME=${0##*/}
+SCRIPT_PATH=${0%/*}
+CWD=`pwd`
+
+# When this script is executed as 'gast_rpmbuild', this script creates symbolic link
+# file name as 'rpmbuild' and exit.
+if [ "${SCRIPT_NAME}" = "${ORIGINAL_NAME}" ]; then
+    for arg in "$@"
+    do
+        case "${arg}" in
+        '--version'|'-v')
+            echo "${ORIGINAL_NAME} ${VERSION}"
+            exit 0
+            ;;
+        '--help'|'-h')
+            cat <<EOL
+usage : ${ORIGINAL_NAME} [-v|--version] [-h|--help]
+
+  -h, --help              display this help and exit
+  -v, --version           display version information and exit
+
+  When this script is executed as '${ORIGINAL_NAME}' with no option, this script 
+  creates symbolic link toward itself which name is 'rpmbuild'.
+
+  When this script is executed as 'rpmbuild', this script behaves just as
+  rpmbuild command with accepting additional '--save-temps-dir' option and
+  with setting GAST_* environment variables.
+EOL
+            exit 0
+            ;;
+        *)
+            echo "usage : ${ORIGINAL_NAME} [--version|-v] [--help|-h]"
+            exit 1
+            ;;
+        esac
+    done
+
+    cd "${SCRIPT_PATH}"
+    for cmd in rpmbuild
+    do
+        if [ -e "${cmd}" ]; then
+            file "${cmd}" 2>/dev/null | egrep 'symbolic link' >/dev/null 2>&1
+            if [ "$?" -ne 0 ]; then
+                echo "${ORIGINAL_NAME} : '${cmd}' exists as normal file or directory. Could not create symbolic link." >&2
+                continue
+            fi
+        fi
+        ln -sf "${ORIGINAL_NAME}" "${cmd}"
+        if [ "$?" -eq 0 ]; then
+            echo "${ORIGINAL_NAME} : Create symbolic link ${cmd}" >&2
+        else
+            echo "${ORIGINAL_NAME} : Couldn't create symbolic link ${cmd}" >&2
+        fi
+    done
+    exit 0
+fi
+
+# get a full-path name of original rpmbuild/rpm2cpio command.
+RPMBUILD_BIN=`which rpmbuild 2>/dev/null`
+if [ -z "${RPMBUILD_BIN}" ]; then
+    echo "${ORIGINAL_NAME} : Couldn't find a path to rpmbuild command. exit" >&2
+    exit 1
+fi
+
+# get a directory path (full-path) of directory this script
+case "${SCRIPT_PATH}" in
+    '.')       SCRIPT_PATH="${CWD}" ;;
+    \./*)      SCRIPT_PATH="${CWD}/${SCRIPT_PATH#*/}" ;;
+    '~')       SCRIPT_PATH="${HOME}" ;;
+    \~/*)      SCRIPT_PATH="${HOME}/${SCRIPT_PATH#*/}" ;;
+    \/*)               :       ;;
+    *)         SCRIPT_PATH="${CWD}/${SCRIPT_PATH}" ;;
+esac
+
+# Set this script's directory to PATH environment variable.
+# (to be found a gcc wrapper script (=gast) in advance of original compiler binary).
+PATH="${SCRIPT_PATH}:${PATH}"
+export PATH
+
+# Set environment variable to get compiler's temporalry file
+export GAST_ENABLE=
+
+# Analyse command options. Get directory name to move temporary file.
+next_is_savedir=
+idx=0
+# new_args_a : argument list for rpmbuild {-bb|-bc}
+# new_args_b : argument list for rpmbuild {--recompile|--rebuild}
+# srpm_list  : list of srpm file(s)
+for arg in "$@"
+do
+    if [ "${arg}" = "--save-temps-dir" ]; then
+        next_is_savedir="yes"
+    elif [ -n "${next_is_savedir}" ]; then
+        next_is_savedir=
+        case "${arg}" in
+            \-*)       GAST_SAVE_DIR=""
+                        echo "${ORIGINAL_NAME} : Error in --save-temps-dir option. ignore this option." >&2
+                        new_args[$idx]="${arg}"
+                        let idx+=1
+                        ;;
+            '')                GAST_SAVE_DIR="" ;;
+            '.')       GAST_SAVE_DIR="${CWD}" ;;
+            \./*)      GAST_SAVE_DIR="${CWD}/${arg#*/}" ;;
+            '~')       GAST_SAVE_DIR="${HOME}" ;;
+            \~/*)      GAST_SAVE_DIR="${HOME}/${arg#*/}" ;;
+            \/*)       GAST_SAVE_DIR="${arg}" ;;
+            *)         GAST_SAVE_DIR="${CWD}/${arg}" ;;
+        esac
+
+        if [ -n "${GAST_SAVE_DIR}" ]; then
+            GAST_SAVE_DIR="${GAST_SAVE_DIR%/}"
+            export GAST_SAVE_DIR
+        else
+            unset GAST_SAVE_DIR
+        fi
+    else
+        new_args[$idx]="${arg}"
+        let idx+=1
+    fi
+done
+exec "${RPMBUILD_BIN}" "${new_args[@]}"