コンパイルとリンク ― 2014年10月01日 20:17
これまでに、copy.for,getc2.for,put2.forが出てきて、copyを実行させるパーツがそろったので、 実際に、作成し実行してみます。
ソースファイルなどを格納するフォルダーは下記の通りです。
- ratfor\fortran\src -- Watcom Fortran77版のソースファイル
- ratfor\fortran\obj -- Watcom Fortran77版のソースファイルから作ったオブジェクトファイル
- ratfor\fortran\exe -- Watcom Fortran77版の実行形式ファイル
- ratfor\fortran\bat -- Watcom Fortran77版のコンパイル・リンク用バッチファイル
- ratfor\ratfor\src -- RATFOR版のソースファイル
- ratfor\ratfor\obj -- RATFOR版のソースファイルから作ったオブジェクトファイル
- ratfor\ratfor\exe -- RATFOR版の実行形式ファイル
- ratfor\ratfor\bat -- RATFOR版ののコンパイル・リンク用バッチファイル
最初に、Watcom Fortran77用の バッチファイルを作成しておきましょう。まずは、コンパイル用。fc.bat
@echo off rem fc.for wfc386 ..\src\%1.for move ..\bat\%1.obj ..\obj
リンケージ用。fl.bat
@echo off rem fl.bat wlink file ..\obj\%1.obj lib ..\obj\ratfor.lib move ..\obj\%1.exe ..\exe
オブジェクト・プログラム・ライブラリーのメンテナンス用。fo.bat
@echo off rem fo.bat wlib ..\obj\ratfor.lib -+..\obj\%1.obj
早速コンパイルしてみましょう。コマンド・プロンプトをあけて、 バッチファイルのあるディレクトリに移動して、 コンパイルします。
Microsoft Windows [Version 6.3.9600] (c) 2013 Microsoft Corporation. All rights reserved. C:\Users\Hiroya>cd Documents\ratfor\fortran\bat C:\Users\Hiroya\Documents\ratfor\fortran\bat>fc getc2 Open Watcom FORTRAN 77/32 Optimizing Compiler Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. ..\src\getc2.for: 27 ステートメント, 166 バイト, 6 拡張メッセージ, 0 警告エラー, 0 エラー 1 個のファイルを移動しました。
getc2.objをratfor.libに登録します。
C:\Users\Hiroya\Documents\ratfor\fortran\bat>fo getc2 Open Watcom Library Manager Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. Warning! '..\obj\ratfor.lib'をオープンできません - ライブラリを作成します C:\Users\Hiroya\Documents\ratfor\fortran\bat>
同様にputc2をコンパイルしratfor.libに登録します。
C:\Users\Hiroya\Documents\ratfor\fortran\bat>fc putc2 Open Watcom FORTRAN 77/32 Optimizing Compiler Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. ..\src\putc2.for: 16 ステートメント, 113 バイト, 4 拡張メッセージ, 0 警告エラー, 0 エラー 1 個のファイルを移動しました。 C:\Users\Hiroya\Documents\ratfor\fortran\bat>fo putc2 Open Watcom Library Manager Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. C:\Users\Hiroya\Documents\ratfor\fortran\bat>
copyをコンパイルし、ライブラリーとリンクします。
C:\Users\Hiroya\Documents\ratfor\fortran\bat>fc copy Open Watcom FORTRAN 77/32 Optimizing Compiler Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. ..\src\copy.for: 8 ステートメント, 35 バイト, 5 拡張メッセージ, 0 警告エラー, 0 エラー 1 個のファイルを移動しました。 C:\Users\Hiroya\Documents\ratfor\fortran\bat>fl copy Open Watcom Linker Version 1.9 Portions Copyright (c) 1985-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. オブジェクトファイルを読込み中 ライブラリを検索中 a Windows NT character-mode 実行可能 を作成中 1 個のファイルを移動しました。 C:\Users\Hiroya\Documents\ratfor\fortran\bat>
テストします。
C:\Users\Hiroya\Documents\ratfor\fortran\bat>cd ..\exe C:\Users\Hiroya\Documents\ratfor\fortran\exe>.\copy test sample test sample looooooooooooong text looooooooooooong text ^Z C:\Users\Hiroya\Documents\ratfor\fortran\exe>.\copy <..\src\copy.for c copy.for -- copy input characters to output program copy integer*1 getc integer*1 c while (getc(c) .ne. -1) do ! EOF(-1) call putc(c) end while stop end C:\Users\Hiroya\Documents\ratfor\fortran\exe>
いかがでしょうか。うまくいったでしょうか。でも、問題が一つあります。NEWLINEがくる前に EOFがくると、その行は、コピーされません。
C:\Users\Hiroya\Documents\ratfor\fortran\exe>.\copy 12345 12345 abcdef^Z C:\Users\Hiroya\Documents\ratfor\fortran\exe>
これは、read文の仕様のようです。従って読み込み行の終わりには必ずNEWLINEがくる事として、 ロジックを考えていきます。また、行の書き出し中にNEWLINEの前にEOFが出現した場合、書き出し途中の 文字列を強制的に書き出すようにします。この変更をしたputc()は、下記のとおり。
c putc3.for (extended version 2)-- put sharacter on standard output subroutine putc(c) integer*1 c integer*1 buf(80) ! MAXCARD(80) integer i,lastc data lastc/0/ if ((c .eq. -1) .and. (lastc .eq. 0)) then ! EOF(-1) return ! buffer is empty endif if ((lastc .ge. 80) .or. (c .eq. 10) .or. (c .eq. -1)) then ! MAXCARD(80) NEWLINE(10) EOF(-1) write(6,100) (buf(i),i=1,lastc) 100 format(80a1) ! MAXCARD(80) lastc = 0 endif if (c .ne. 10) then ! NEWLINE(10) lastc = lastc + 1 buf(lastc) = c endif return end
コンパイルとライブラリーへの追加は下記のとおり。
C:\Users\Hiroya\Documents\ratfor\fortran\bat>fc putc3 Open Watcom FORTRAN 77/32 Optimizing Compiler Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. ..\src\putc3.for: 19 ステートメント, 129 バイト, 4 拡張メッセージ, 0 警告エラー, 0 エラー 1 個のファイルを移動しました。 C:\Users\Hiroya\Documents\ratfor\fortran\bat>cd ..\obj C:\Users\Hiroya\Documents\ratfor\fortran\obj>wlib ratfor -putc2 +putc3 Open Watcom Library Manager Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details.
putc()が新しくなりましたので、copyを作成し直してください。
コマンド行の引数 ― 2014年10月05日 11:01
コマンドラインのプログラムには、引数をつけることで、プログラムに様々な 情報を与えています。この引数を受け取る関数getargを作ります。これは、 Watcom Fortran77の拡張機能iargc(),igetarg()を使い実現します。プログラムは次の通り。
c getarg.for -- get n-th command line argument integer function getarg(n,arg,maxsiz) integer n, maxsiz integer*1 arg(maxsiz) character*100 carg integer*1 iarg(100) equivalence (carg,iarg) integer l integer iargc,igetarg if (n .ge. iargc()) then getarg = -1 ! EOF(-1) arg(1) = -2 ! EOS(-2), return NULL string return endif l = igetarg(n,carg) i = 1 while (i .le. l .and. i .le. maxsiz) do arg(i) = iarg(i) i = i + 1 end while arg(i) = -2 ! EOS(-2) <<< BUF FIX 10/12 getarg = i - 1 ! <<< BUF FIX 10/12 return end
igetc()は、コマンドラインの引数の数を返します。これには、コマンド自身も含まれます。igetarg(n,str)は、 n番目の引数をcharacter型の文字列strにコピーし長さを返します。strはこのままでは使えないので、integer*1の 文字列に変換し利用します。getarg(n,arg,maxsiz)は、n番目の引数を最大maxsiz文字分argにコピーし、 引数があればYES(1)を そうでなければNO(0)を返します。
getarg()を使った例題echoを示します。コマンドラインの引数を表示する簡単なものです。
まずは、RATFOR版
# echo.r4 -- echo command line arguments character arg(MAXARG) integer i,n integer getarg for (n = 1; getarg(n,arg,MAXARG) != EOF; n = n + 1) { for (i = 1; arg(i) != EOS; i = i + 1) call putc(arg(i)) call putc(BLANK) } call putc(NEWLINE) stop end
Watcom Fortran77版
c echo.for -- echo command line arguments program echo integer*1 arg(100) ! MAXARG(100) integer i,n integer getarg n = 1 while (getarg(n,arg,100) .ne. -1) do ! MAXARG(100) EOF(-1) i = 1 while(arg(i) .ne. -2) do ! EOS(-2) call putc(arg(i)) i = i + 1 end while call putc(32) ! BLANK(32) n = n + 1 end while call putc(10) ! NEWLINE(10) stop end
早速、コンパイルしてみましょう。
C:\Users\Hiroya\Documents\ratfor\fortran\bat>fc getarg Open Watcom FORTRAN 77/32 Optimizing Compiler Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. ..\src\getarg.for: 23 ステートメント, 95 バイト, 7 拡張メッセージ, 0 警告エラー, 0 エラー 1 個のファイルを移動しました。 C:\Users\Hiroya\Documents\ratfor\fortran\bat>fo getarg Open Watcom Library Manager Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. C:\Users\Hiroya\Documents\ratfor\fortran\bat>fc echo Open Watcom FORTRAN 77/32 Optimizing Compiler Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. ..\src\echo.for: 17 ステートメント, 112 バイト, 5 拡張メッセージ, 0 警告エラー, 0 エラー 1 個のファイルを移動しました。 C:\Users\Hiroya\Documents\ratfor\fortran\bat>fl echo Open Watcom Linker Version 1.9 Portions Copyright (c) 1985-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. オブジェクトファイルを読込み中 ライブラリを検索中 a Windows NT character-mode 実行可能 を作成中 1 個のファイルを移動しました。 C:\Users\Hiroya\Documents\ratfor\fortran\bat>
テストします。
C:\Users\Hiroya\Documents\ratfor\fortran\bat>cd ..\exe C:\Users\Hiroya\Documents\ratfor\fortran\exe>.\echo one two three one two three C:\Users\Hiroya\Documents\ratfor\fortran\exe>.\echo one "t w o" three one t w o three C:\Users\Hiroya\Documents\ratfor\fortran\exe>
ダブルクォートで囲むと、ブランクも含めて引き渡すことができます。
数字出力putdec() ― 2014年10月12日 19:32
先に出てきたputdec(n,w)をみてみましょう。 数値nをw桁で印字します。必要があれば、桁は拡張されます。
RATFOR版は下記の通り。
# putdec.r4 -- put decimal integer n in field width >= W subroutine putdec(n, w) character chars(MAXCHARS) integer itoc integer i, n, nd, w nd = itoc(n, chars, MAXCHARS) for ( i = nd + 1; i <= w; i = i + 1) call putc(BLANK) for ( i = 1; i <= nd; i = i + 1) call putc(chars(i)) return end
ここで、itoc(n,chars,MAXCHARS)は、数値nを長さMAXCHARS文字の文字配列charsに変換します。
RATFOR版は下記の通り。
# itoc.r4 -- convert integer int to character string str integer fnction itoc(int, str, size) integer abs, mod integer d, i, int, intval, j, size character str(size), k string digits "0123456789" intval = abs(int) str(1) = EOS i = 1 repeat { # generate digits i = i + 1 d = mod(intval, 10) str(i) = digits(d + 1) intval = intval / 10 } until (intval == 0 ! i >= size) if (int < 0 & i < size) { # then sign i = i + 1 str(i) = MINUS } itoc = i - 1 for (i = 1; j < i; j = j + 1) { # then reverse k = str(i) str(i) = str(j) str(j) = k i = i - 1 } return end
string deigits "0123456789"とは、文字を文字配列にセットするマクロで、
character digits(11) data digit(1) /'0'/ data digit(2) /'1'/ data digit(3) /'2'/ data digit(4) /'3'/ data digit(5) /'4'/ data digit(6) /'5'/ data digit(7) /'6'/ data digit(8) /'7'/ data digit(9) /'8'/ data digit(10) /'9'/ data digit(11) /EOS/と展開されます。EOSは文字列の終わりを示す記号です。
Watcom Fortran77版のputdec()、itoc()は下記の通り。
c putdec.for -- put decimal integer n in field width >= w subroutine putdec(n,w) integer n, w integer*1 chars(100) ! MAXCHARS(100) integer itoc, nd nd = itoc(n, chars, 100) ! MAXCHARS(100) i = nd + 1 while (i .le. w) do call putc(32) ! BLANK(32) i = i + 1 end while i = 1 while (i .le. nd) do call putc(chars(i)) i = i + 1 end while return end
c itoc.for -- convert integer int to character string in str integer function itoc(int,str,size) integer int, size integer*1 str(size) integer abs, mod integer d, i, intval, j integer*1 digits(11), k data digits/'0','1','2','3','4','5','6','7','8','9',-2/ ! EOS(-2) intval = abs(int) str(1) = -2 ! EOS(-2) i = 1 loop i = i + 1 ! generate digits d = mod(intval,10) str(i) = digits(d+1) intval = intval / 10 until ((intval .eq. 0) .or. (i .ge. size)) if ((int .lt. 0) .and. (i .lt. size)) then ! then sign i = i + 1 str(i) = 45 ! MINUS(45) endif itoc = i - 1 j = 1 while (j .lt. i) do ! then reverse k = str(i) str(i) = str(j) str(j) = k i = i - 1 j = j + 1 end while return end
ここまでで、charcount、wordcount、linecountのパーツがそろいましたので、 この3つをビルドしてみます。
まず、putdec()、itoc()を作成します。
C:\Users\Hiroya\Documents\ratfor\fortran\bat>fc putdec Open Watcom FORTRAN 77/32 Optimizing Compiler Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. ..\src\putdec.for: 17 ステートメント, 92 バイト, 4 拡張メッセージ, 0 警告エラー, 0 エラー 1 個のファイルを移動しました。 C:\Users\Hiroya\Documents\ratfor\fortran\bat>fo putdec Open Watcom Library Manager Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. C:\Users\Hiroya\Documents\ratfor\fortran\bat>fc itoc Open Watcom FORTRAN 77/32 Optimizing Compiler Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. ..\src\itoc.for: 31 ステートメント, 172 バイト, 6 拡張メッセージ, 0 警告エラー, 0 エラー 1 個のファイルを移動しました。 C:\Users\Hiroya\Documents\ratfor\fortran\bat>fo itoc Open Watcom Library Manager Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details.
charcountをビルドします。
C:\Users\Hiroya\Documents\ratfor\fortran\bat>fc charcount Open Watcom FORTRAN 77/32 Optimizing Compiler Version 1.9 Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. ..\src\charcount.for: 12 ステートメント, 69 バイト, 5 拡張メッセージ, 0 警告エラー, 0 エラー 1 個のファイルを移動しました。 C:\Users\Hiroya\Documents\ratfor\fortran\bat>fl charcount Open Watcom Linker Version 1.9 Portions Copyright (c) 1985-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. オブジェクトファイルを読込み中 ライブラリを検索中 a Windows NT character-mode 実行可能 を作成中 1 個のファイルを移動しました。
テストします。
C:\Users\Hiroya\Documents\ratfor\fortran\bat>..\exe\charcount 123 456 7890 ^Z 13
wordcount、linecountも同様にビルドしてください。
文字から数値への変換 ― 2014年10月19日 19:22
さて、itoc()の逆の関数をctoi(c,i)を作っておきます。これは、文字配列cのi番目から数値に変換します。
RATFOR版は次の通り。
# ctoi.r4 -- convert string at in(i) to integer, increment i integer ctoi(in,i) character in(ARB) integer iindex integer d, i string digits "0123456789" while (in(i) == BLANK | in(i) == TAB) i = i + 1 for (ctoi = 0; in(i) != EOS; i = i + 1) { d = iindex(digits, in(i)) if (d == 0) # non-digit break ctoi = ctoi * 10 + d - 1 } return end
ここで、iindex(s,c)は、文字配列sの中から文字cを探しその位置を返します。Watcom Fortran77には、 同様の組み込み関数index()がありますが、引数がchracter型であるため使えません。作り直します。
RATFOR版は下記の通り。
# iindex.r4 -- find character c in string str integer function iindex(str,c) character c,str(ARB) for (iindex = 1; str(iindex) != EOS; iindex = iindex + 1) if (str(iindex) == c) return iindex = 0 return end
ctoi()、iindex()のWatcom Fortran77版は、下記の通り。
c ctoi.for -- convert string at in(i) to integer, increment i integer function ctoi(in,i) integer*1 in(*) ! ARB(*) integer i, d integer iindex integer*1 digits(11) data digits/'0','1','2','3','4','5','6','7','8','9',-2/ ! EOS(-2) while ((in(i) .eq. 32) .or. (in(i) .eq. 9)) do ! BLANK(32) TAB(9) i = i + 1 end while ctoi = 0 while (in(i) .ne. -2) do ! EOS(-2) d = iindex(digits,in(i)) if (d .eq. 0) then exit end if ctoi = ctoi*10 + (d - 1) i = i + 1 end while ctoi = ctoi return end
c iindex.for -- find charcter c instring str integer function iindex(str,c) integer*1 c,str(*) iindex = 1 while (str(iindex) .ne. -2) do ! EOS(-2) if (str(iindex) .eq. c) then return end if iindex = iindex + 1 end while iindex = 0 return end
"+"や"-"の付いた数字列を取り扱えるようにctoi()を拡張しておくのは、有意義なことです。拡張版は、次の通り。
c ctoi2.for -- (extended vertion 1) convert string at in(i) to integer, increment i integer function ctoi(in,i) integer*1 in(*) ! ARB(*) integer i integer iindex integer d, s integer*1 digits(11) data digits/'0','1','2','3','4','5','6','7','8','9',-2/ ! EOS(-2) while ((in(i) .eq. 32) .or. (in(i) .eq. 9)) do ! BLANK(32) TAB(9) i = i + 1 end while ctoi = 0 if (in(i) .eq. 43) then ! PLUS(43) s = 1 i = i + 1 else if (in(i) .eq. 45) then ! MINUS(45) s = -1 i = i + 1 else s = 1 end if while (in(i) .ne. -2) do ! EOS(-2) d = iindex(digits, in(i)) if (d .eq. 0) then exit end if ctoi = ctoi * 10 + (d - 1) i = i + 1 end while ctoi = s*ctoi return end
最近のコメント