change -- 文書ファイルの書き換え2015年09月06日 14:51

changeは、指定された文字列"原型"を 別の文字列"更新型"に置換します。

     change 原型 更新型

更新型には繰り返し記号"#"を含ませることができる。"#"は原型を表す。

     change foo #bar
とすれば、出現した"foo"は、"foobar"に置き換えられる。

changeはfindで使用したルーチンを利用して作成してある。まずは、メインルーチンから。

RATFOR版は以下の通り。

# change -- change "from" into "to"
      character lin(MAXLINE+1),new(MAXLINE+1),pat(MAXPAT),sub(MAXPAT)
      character arg(MAXARG)
      integer amatch,addset,getarg,getlin,getpat,getsub
      integer i,junk,k,lastm,m

      if (getarg(1,arg,MAXARG) == EOF)
          call error('usage: change from to.')
      if (getpat(arg,pat) == ERR)
          call error('illigal from pattern.')
      if (getarg(2,arg,MAXARG))
          arg(1) = EOS
      if ( getsub(arg,sub) == ERR)
          call error('illigal to.')

      while (getlin(lin,STDIN) .ne. EOF) {
          k = 1
          lastm = 0
          for (i = 1; lin(i) != EOS; ) {
              m = amatch(lin,i,pat)
              if (m > 0 & lastm != m) # replace matched text
                  call catsub(lin,i,m,sub,new,k,MAXLINE+1)
                  lastm = m
                  }
              if (m == 0 | m == i) {
                  junk = addset(lin(i),new,k,MAXLINE+1)
                  i = i + 1
                  }
              else
                  i = m
              }
          if (addset(EOS,new,k,MAXLINE+1) == NO) {
              k = MAXLINE + 1
              junk = addset(EOS,new,k,MAXLINE+1)
              call remark('line truncated.')
              call putlin(new,ERROUT)
              call fputc(ERROUT,NEWLINE)
              }
          call putlin(new,STDOUT)
          }
      stop
      end

WATCOM Fortran77版は下記の通り。

c change -- change "from" into "to"
      integer*1 lin(81+1),new(81+1),pat(81),sub(256) ! MAXLINE(81) MAXPAT(81)
      integer*1 arg(81)                 ! MAXARG(81)
      integer amatch,addset,getarg,getlin,getpat,getsub
      integer i,junk,k,lastm,m

      call initfile()

      if (getarg(1,arg,81) .eq. -1) then ! MAXARG(81) EOF(-1)
          call error('usage: change from to.')
      end if
      if (getpat(arg,pat) .eq. -1 ) then ! EOF(-1)
          call error('illigal from pattern.')
      end if
      if (getarg(2,arg,81) .eq. -1) then ! MAXLARG(81) EOF(-1)
          arg(1) = -2                  ! EOS(-2)
      end if
      if ( getsub(arg,sub) .eq. -1) then ! ERR(-1)
          call error('illigal to.')
      end if

      while (getlin(lin,5) .ne. -1) do  ! STDIN(5) EOF(-1)
          k = 1
          lastm = 0
          i = 1
          while (lin(i) .ne. -2) do     ! EOS(-2)
              m = amatch(lin,i,pat)
              if ((m .gt. 0) .and. (lastm .ne. m)) then ! replace matched text
                  call catsub(lin,i,m,sub,new,k,81+1) ! MAXLINE(81)
                  lastm = m
              end if
              if ((m .eq. 0) .or. (m .eq. i)) then
                  junk = addset(lin(i),new,k,81+1) ! MAXLINE(81)
                  i = i + 1
              else
                  i = m
              end if
          end while
          if (addset(-2,new,k,81+1) .eq. 0) then ! EOS(-2) NAXLINE(81) NO(0)
              k = 81+1                  ! MAXLINE(81)
              junk = addset(-2,new,k,81+1) ! EOS(-2) NAXLINE(81)
              call remark('line truncated.')
              call putlin(new,6)        ! ERROUT(6)
              call fputc(6,10)          ! ERROUT(6) NEWLINE(10)
          end if
          call putlin(new,6)
      end while
      stop
      end

下請けルーチンgetsub()は、置き換え文型を組み立てる。

RATFOR版は下記の通り。

# getsub -- get substitution pattern into sub
      integer function getsub(arg,sub)
      character arg(MAXARG),sub(MAXPAT)
      integer maksub

      getsub = maksub(arg,1,EOS,sub)
      return
      end

WATCOM Fortran77版は下記の通り。

c getsub -- get substitution pattern into sub
      integer function getsub(arg,sub)
      integer*1 arg(81),sub(81)         ! MAXARG(81) MAXPAT(81)
      integer maksub

      getsub = maksub(arg,1,-2,sub)     ! EOS(-2)
      return
      end

maksub()は、置き換え文字列を作成します。繰り返し記号"#"は、特別な記号に置き換えられます。

RATFOR版は下記の通り。

# maksub -- make subtitution string in sub
      integer function maksub(arg,from,delim,sub)
      character arg(MAXARG),delim,sub(MAXPAT)
      integer from
      character esc
      integer addset,i,j,junk

      j = 1
      for (i = from; arg(i) != delim & arg(i) != EOS; i = i + 1)
          if (arg(i) == SHARP 
              junk = addset(DITTO,sub,j,MAXPAT)
          else
              junk = addset(esc(arg,i),sub,j,MAXPAT)
      if (arg(i) != delim) then # missing delimiter
          maksub = ERR
      else if (.not. addset(EOS,sub,j,MAXPAT)) then # no room
          maksub = ERR
      else
          maksub = i
      return
      end

WATCOM Fortran77版は下記の通り。

c maksub -- make subtitution string in sub
      integer function maksub(arg,from,delim,sub)
      integer*1 arg(81),delim,sub(81)   ! MAXARG(81) MAXPAT(81)
      integer from
      integer*1 esc
      integer addset,i,j,junk

      j = 1
      i = from
      while ((arg(i) .ne. delim) .and. (arg(i) .ne. -2)) do  ! EOS(-2)
          if (arg(i) .eq. 35) then      ! SHARP(35 '#')
              junk = addset(-3,sub,j,81) ! DITTO(-3) MAXPAT(81)
          else
              junk = addset(esc(arg,i),sub,j,81) ! MAXPAT(81)
          end if
          i = i + 1
      end while
      if (arg(i) .ne. delim) then       ! missing delimiter
          maksub = -1                   ! ERR(-1)
      else if (addset(-2,sub,j,81) .eq. 0) then ! no room ! EOS(-2) MAXPAT81) NO(0)
          maksub = -1                   ! ERR(-1)
      else
          maksub = i
      end if
      return
      end

catsub()で、置き換えられた文字列を出力用文字列に追加します。 繰り返し記号が出てきたら、まず原型を追加します。

RATFOR版は下記の通り。

# catsub -- add replacement text to end of new
      subroutine catsub(lin,from,to,sub,new,k,maxnew)
      character lin(MAXLINE+1),sub(CMAXPAT),new(maxnew)
      integer from,to,k,maxnew
      integer addset,i,j,junk

      for (i = 1; sub(i) != EOS; i = i + 1) do
          if (sub(i) == DITTO)
              for (j = from; j < to; j = j + 1) 
                  junk = addset(lin(j),new,k,maxnew)
          else
              junk = addset(sub(i),new,k,maxnew)
      return
      end

WATCOM Fortran77版は下記の通り。

c catsub -- add replacement text to end of new
      subroutine catsub(lin,from,to,sub,new,k,maxnew)
      integer*1 lin(81+1),sub(81),new(maxnew) ! MAXLINE(81) MAXPAT(81)
      integer from,to,k,maxnew
      integer addset,i,j,junk

      i = 1
      while (sub(i) .ne. -2) do         ! EOS(-2)
          if (sub(i) .eq. -3) then      ! DITTO(-3)
              j = from
              while (j .lt. to) do
                  junk = addset(lin(j),new,k,maxnew)
                  j = j + 1
              end while
          else
              junk = addset(sub(i),new,k,maxnew)
          end if
          i = i + 1
      end while
      return
      end