Gauche:scm2cmd

Gauche:scm2cmd

具体的には任意のGaucheスクリプトの先頭に以下を、

;@rem -*- mode: scheme -*-
;@echo off
;gosh "%~f0" %*
;goto :__gauche_script_end

最後に

;
;:__gauche_script_end
;

を挿入し、ファイルの拡張子を .cmd にします。

これによりWindows上で任意のスクリプトをそのまま実行ファイルにできます。

末尾部分はの3行それぞれ「次の行を確実に行頭にする」、「バッチファイルの終了時にgotoで移動する場所」、「cmd.exeがコマンド終了時に挿入する改行を抑制」という意味があります。その性質上1行目と3行目は単なる空行でも構いませんが、何か見えた方が分かりやすいのでこうしました。

もちろん、 windows 上では ftype コマンドと assoc コマンドを用いればこのような事をせずに実行ファイルにできるのですが、リダイレクトができなくなる等問題があり、バッチファイルにする事はある程度の意義があります。

以上の操作を行なわせるスクリプトを以下に示します。 このスクリプトを用いたスクリプトを使用する時はあらかじめ gosh にPATHを通しておくかスクリプト上の gosh をフルパス指定して下さい。

バッチファイルはコマンド入力時に拡張子を省略して実行できるのでUnix上のGaucheスクリプトと同じようにプログラムを実行できます。ただし、この記法はUnixの #! 記法とは互換性が無いので注意して下さい。

filename: scm2cmd.scm

#!/usr/bin/gosh
;; scm2cmd by YOKOTA Hiroshi
#|
=head1 NAME

scm2cmd - wrap Gauche code into a MS Windows batch file

=head1 SYNOPSIS

B<scm2cmd> B<-h>

B<scm2cmd> S<[B<-o> I<output_file>]> I<input_file>

=head1 DESCRIPTION

This utility converts a Gauche script into a batch file that can be
executed on DOS-like operating systems. This is intended to allow
you to use a Gauche script like regular programs and batch files where
you just enter the name of the script [probably minus the extension]
plus any command-line arguments and the script is found in your B<PATH>
and run.

=head1 OPTIONS

=over 8

=item B<-h>

Show usage.

=item B<-o> I<output_file>

Specify output file name. If this option is not specified, make output
file name from input file name.

=head1 SEE ALSO

gosh

=cut
|#

(use gauche.parseopt)

(define (usage)
  (print "Usage: scm2cmd [-o outfile] <script>")
  (exit 0))

(define (main args)
  (let-args (cdr args) ((outfile "o=s")
                        (help "h|help" => (cut usage))
                        . args)

            (when (null? args) (usage))

            (let* ((ifile (car args))
                   (ofile (or outfile
                              (if (#/\.scm$/ ifile)
                                  (regexp-replace #/\.scm$/ ifile ".cmd")
                                  #`",|ifile|.cmd"))))

              (with-output-to-file ofile
                (lambda ()
                  (for-each print '(";@rem -*- mode: scheme -*-"
                                    ";@echo off"
                                    ";gosh \"%~f0\" %*"
                                    ";goto :__gauche_script_end"))
                  (with-input-from-file ifile
                    (lambda () (copy-port (current-input-port)
                                          (current-output-port))))
                  (for-each print '(";"
                                    ";:__gauche_script_end"
                                    ";"))
                  )))))

; end
More ...