引数付きマクロ処理 -- 機能拡張(2)2017年04月14日 19:53

組み込み関数"ifelse"の実装は以下の通り。

RATFOR版

# doif.f -- select one of two arguments
      include ratfor.def
      subroutine doif(argstk,i,j)
      integer i,j,argstk(ARGSIZE)
      integer equal
      integer a2,a3,a4,a5

      include cmacro.ri

      if (j-i < 5)
          return

      a2 = argstk(i + 2)
      a3 = argstk(i + 3)
      a4 = argstk(i + 4)
      a5 = argstk(i + 5)

      if (equal(evalst(a2),evalst(a3)) == YES)
          call pbstr(evalst(a4))
      else
          call pbstr(evalst(a5))
      return
      end

WATCOM Fortran 77版は以下の通り。

c doif.f -- select one of two arguments
      include ratfor.def
      subroutine doif(argstk,i,j)
      integer i,j,argstk(ARGSIZE)
      integer equal
      integer a2,a3,a4,a5

      include cmacro.fi

      if (j-i .lt. 5) then
          return
      end if

      a2 = argstk(i + 2)
      a3 = argstk(i + 3)
      a4 = argstk(i + 4)
      a5 = argstk(i + 5)

      if (equal(evalst(a2),evalst(a3)) .eq. YES) then
          call pbstr(evalst(a4))
      else
          call pbstr(evalst(a5))
      end if
      return
      end

組み込み関数"incr"は、引数を数値化して、下請けルーチンpbnum()で+1し、文字列化して入力に戻す。"incr"の実装は 以下の通り。

RATFOR版

# doinc.r4 -- increment argument by 1
      include ratfor.def
      subroutine doincr(argstk,i,j)
      integer i,j,argstk(ARGSIZE)
      integer ctoi
      integer k

      include cmacro.ri

      k = argstk(i+2)
      call pbnum(ctoi(evalst,k)+1)
      return
      end

WATCOM Fortran 77版は以下の通り。

c doinc.f -- increment argument by 1
      include ratfor.def
      subroutine doinc(argstk,i,j)
      integer i,j,argstk(ARGSIZE)
      integer ctoi
      integer k

      include cmacro.fi

      k = argstk(i+2)
      call pbnum(ctoi(evalst,k)+1)
      return
      end

下請けルーチンpbnum()は以下の通り。

RATFOR版は以下の通り。

# pbnum.r4 -- convert number to string, push back on input
      include ratfor.def
      subroutine pbnum(n)
      integer n
      integer mod
      integer m,num
      string digits "0123456789"

      num = n
      repeat {
          m = mod(num,10)
          call putbak(digits(m+1))
          num = num/10
          } until (num == 0)
      return
      end

WATCOM Fortran 77版は以下の通り。

c pbnum.f -- convert number to string, push back on input
      include ratfor.def
      subroutine pbnum(n)
      integer n
      integer mod
      integer m,num
      integer*1 digits(11)
      data digits(1)/LET0/
      data digits(2)/LET1/
      data digits(3)/LET2/
      data digits(4)/LET3/
      data digits(5)/LET4/
      data digits(6)/LET5/
      data digits(7)/LET6/
      data digits(8)/LET7/
      data digits(9)/LET8/
      data digits(10)/LET9/
      data digits(11)/EOS/

      num = n
      loop
          m = mod(num,10)
          call putbak(digits(m+1))
          num = num/10
      until (num .eq. 0)
      return
      end

組み込み関数"substr"の実装は、以下の通り。

RATFOR版は以下の通り。

# dosub.r4 -- select substring
      include ratfor.def
      subroutine dosub(argstk,i,j)
      integer i,j,argstk(ARGSIZE)
      integer ctoi,length,min
      integer ap,fc,k,nc

      include cmacro.ri

      if (j-i < 3)
          return
      if (j-i < 4)
          nc = MAXTOK
      else {
          k = argstk(i+4)
          nc = ctoi(evalst,k)           # number of characters
          }
      k = argstk(i+3)                   # origin
      ap = argstk(i+2)                  # target string
      fc = ap + ctoi(evalst,k) - 1      # first char of substring
      if ((fc >= ap) & (fc < ap+length(evalst(ap)))) { # subarrays
          k = fc + min(nc,length(evalst(fc))) - 1
          for ( ; k >= fc ; k = k -1)
              call putbak(evalst(k))
          }
      return
      end

WATCOM Fortran 77版は以下の通り。

c dosub.f -- select substring
      include ratfor.def
      subroutine dosub(argstk,i,j)
      integer i,j,argstk(ARGSIZE)
      integer ctoi,length,min
      integer ap,fc,k,nc

      include cmacro.fi

      if (j-i .lt. 3) then
          return
      end if
      if (j-i .lt. 4) then
          nc = MAXTOK
      else
          k = argstk(i+4)
          nc = ctoi(evalst,k)      ! number of characters
      end if
      k = argstk(i+3)              ! origin
      ap = argstk(i+2)             ! target string
      fc = ap + ctoi(evalst,k) - 1 ! first char of substring
      if ((fc .ge. ap) .and. (fc .lt. ap+length(evalst(ap)))) then ! subarrays
          k = fc + min(nc,length(evalst(fc))) - 1
          while (k .ge. fc) do
              call putbak(evalst(k))
              k = k - 1
          end while
      end if
      return
      end

組み込み関数"undef"の実装は、以下の通り。

RATFOR版

# doudf.f -- undefine macro
      include ratfor.def
      subroutine doudf(argstk,i,j)
      integer i,j,argstk(ARGSIZE)
      integer a2

      include cmacro.r4

      if (j-i .lt. 1)
          return

      a2 = argstk(i + 2)
      call uninst(evalst(a2))
      return
      end

WATCOM Fortran 77版は以下の通り。

c doudf.f -- undefine macro
      include ratfor.def
      subroutine doudf(argstk,i,j)
      integer i,j,argstk(ARGSIZE)
      integer a2

      include cmacro.fi

      if (j-i .lt. 1) then
          return
      end if

      a2 = argstk(i + 2)
      call uninst(evalst(a2))
      return
      end

組み込み関数"ifdef"の実装は、以下の通り。

RATFOR版

# doifd.r4 -- define if macro is defined
      include ratfor.def
      subroutine doifd(argstk,i,j)
      integer i,j,argstk(ARGSIZE)
      integer lookup
      integer a2,a3,a4
      character junk(MAXDEF)

      include cmacro.fi

      if (j-i .lt. 4)
          return

      a2 = argstk(i + 2)
      a3 = argstk(i + 3)
      a4 = argstk(i + 4)
      if (lookup(evalst(a2),junk) .eq. YES)
          call pbstr(evalst(a3))
      else
          call pbstr(evalst(a4))
      return
      end

WATCOM Fortran 77版は以下の通り。

# doifd.r4 -- define if macro is defined
      include ratfor.def
      subroutine doifd(argstk,i,j)
      integer i,j,argstk(ARGSIZE)
      integer lookup
      integer a2,a3,a4
      character junk(MAXDEF)

      include cmacro.fi

      if (j-i .lt. 4)
          return

      a2 = argstk(i + 2)
      a3 = argstk(i + 3)
      a4 = argstk(i + 4)
      if (lookup(evalst(a2),junk) .eq. YES)
          call pbstr(evalst(a3))
      else
          call pbstr(evalst(a4))
      return
      end

マクロの応用を紹介する。

文字列の長さを返す"len"。再帰的定義になっているが、込み入ってない。

          define(len,[ifelse($1,,0,[incr(len(substr($1,2)))])])

文字列を定義する"string"。

           string(name,"STRING")

とすると

           integer name(6)
           data name(1)/LETS/
           data name(2)/LETT/
           data name(3)/LETR/
           data name(4)/LETN/
           data name(5)/LETG/

           data name(6)/EOS/

と展開される。"string"の定義は、以下の通り。

          define(string,[integer $1(len(substr($2,2)))
          str($1,substr($2,2),0)
                data $1(len(substr($2,2)))/EOS/
          ])

下請けルーチンの"str"は、以下の通り。

          define(str,[ifelse($2,",,      data $1(incr($3))/[LET]substr($2,1,1)/
          [str($1,substr($2,2),incr($3))])])

macro.r4中の

      string(balp,"()")
は、うまく展開できない。

コメント

_ jesusacowher.soup.io ― 2017年05月02日 09:37

Hi, Neat post. There&#39;s an issue together with your site in web explorer, may test this?

IE nonetheless is the market chief and a large component of people will leave out your great writing because of this problem.

_ manicure ― 2017年05月03日 12:24

I am extremely impressed with your writing skills as well as with the layout on your
weblog. Is this a paid theme or did you modify it yourself?
Either way keep up the nice quality writing, it&#39;s rare to see
a nice blog like this one these days.

_ choc ― 2018年05月02日 20:17

Neat blog! Is your theme custom made or did you download it
from somewhere? A design like yours with a few simple adjustements would really make my blog shine.
Please let me know where you got your design. Thanks a
lot

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

名前:
メールアドレス:
URL:
コメント:

トラックバック

このエントリのトラックバックURL: http://kida.asablo.jp/blog/2017/04/14/8480456/tb