editメインルーチンdocmd()2016年06月12日 11:09

編集機能は、一部の指令を除いて、基本的に個々の下請けルーチンで行う。 ここのルーチンに分岐するメインインルーチンがdocmd()である。長いけれど、コマンドを調べて 分岐するcase分けである。

挿入指令(.)i、変更指令(.,.)c、行番号打ち出し指令(.)=は、これまでのルーチンで実現できる。

挿入指令(.)iは、以下の通り。

      else if (lin(i) == INSERT) {
          status = append(prevln(line2),glob)
          }

変更指令(.,.)cは、以下の通り。

      else if (lin(i) == CHANGE) {
          if (lin(i+1) == NEWLINE)
              if (defalt(curln,curln,status) == OK)
                  if (delete(line1,line2,status) == OK)
                      status = append(prevln(line1),glob)
          }
S
行番号打ち出し指令(.)=は、以下の通り。
      else if (lin(i) == PRINTCUR) {
          if (ckp(lin,i+1,pflag,status) == OK) {
              call putdec(line2,1)
              call putc(NEWLINE)
              }
          }

docmd()のRATFOR版を以下に示す。

# docmd.r4 -- handle all commands except globals
      integer function docmd(lin,i,glob,status)
      character lin(MAXLINE)
      integer i,glob,status

      integer append,doprnt,defalt,nextln,prevln,move,ckp,getone
      integer dodel,getrhs,subst,getfn,doread,dowrit
      integer line3
      character file(MAXLINE)
      integer pflag,gflag,optpat

      include clines.ri
      include cfile.ri
      include cpat.ri

      pflag = NO
      status = ERR
      if (lin(i) == APPENDCOM) {
          if (lin(i+1) == NEWLINE)
              status = append(line2,glob)
          }
      else if (lin(i) == CHANGE) {
          if (lin(i+1) == NEWLINE)
              if (defalt(curln,curln,status) == OK)
                  if (delete(line1,line2,status) == OK)
                      status = append(prevln(line1),glob)
          }
      else if (lin(i) == DELETE) {
          if (ckp(lin,i+1,pflag,status) == OK)
              if (defalt(curln,curln,status) == OK)
                  if (dodel(line1,line2,status) == OK)
                      if (nextln(curln) == 0)
                          curln = nextln(curln)
          }
      else if (lin(i) == INSERT) {
          if (lin(i+1) == NEWLINE)
              status = append(prevln(line2),glob)
          }
      else if (lin(i) == PRINTCUR) {
          if (ckp(lin,i+1,pflag,status) == OK) {
              call putdec(line2,1)
              call putc(NEWLINE)
              }
          }
      else if (lin(i) MOVECOM) {
          i = i + 1
          if (getone(lin,i,line3,status) == EOF)
              status = ERR
          if (status == OK)
              if (ckp(lin,i,pflag,status) == OK)
                  if (defalt(curln,curln,status) ==OK)
                      status = move(line3)
          }
      else if (lin(i) == SUBSTITUTE) {
          i = i + 1
          if (optpat(lin,i) == OK)
              if (getrhs(lin,i,sub,gflag) == OK)
                  if (ckp(lin,i+1,pflag,status) == OK)
                      if (defalt(curln,curln,status) == OK)
                          status = subst(sub,gflag)
          }
      else if (lin(i) == ENTER) {
          if (nlines == 0) then
              if (getfn(lin,i,file) == OK) {
                  call scopy(file,1,savfil,1)
                  call clrbuf
                  call setbuf
                  status = doread(0,file)
              }
          }
      else if (lin(i) == PRINTFIL) {
          if (nlines == 0)
              if (getfn(lin,i,file) == OK) {
                  call scopy(file,1,savfil,1)
                  call putlin(savfil,STDOUT)
                  call putc(NEWLINE)
                  status = OK
              }
          }
      else if (lin(i) == READCOM) {
          if (getfn(lin,i,file) == OK)
              status = doread(line2,file)
          }
      else if (lin(i) ==WRITECOM) {
          if (getfn(lin,i,file) == OK)
              if (defalt(1,lastln,status) == OK)
                  status = dowrit(line1,line2,file)
              end if
          }
      else if (lin(i) == PRINT) {
          if (lin(i+1) == NEWLINE)
              if (defalt(curln,curln,status) == OK)
                  status = doprnt(line1,line2)
          }
      else if (lin(i) == QUIT) {
          if (lin(i+1) == NEWLINE & nlines == 0 & glob == NO)
              status = EOF
          }
      # else status is ERR
      end if

      if (status == OK & pflag == YES)
          status = doprnt(curln,curln)
      docmd = status
      return
      end

WATCOM Fortran77版は以下の通り。

c docmd.f -- handle all commands except globals
      integer function docmd(lin,i,glob,status)
      integer*1 lin(82)                 ! MAXLINE(82)
      integer i,glob,status

      integer append,doprnt,defalt,nextln,prevln,move,ckp,getone
      integer dodel,getrhs,subst,getfn,doread,dowrit
      integer line3
      integer*1 file(82)                ! MAXLINE(82)
      integer pflag,gflag,optpat

      include clines.fi
      include cfile.fi
      include cpat.fi

      pflag = 0                         ! NO(0)
      status = -3                       ! ERR(-3)
      if (lin(i) .eq. 97) then          ! APPENDCOM(97 'a')
          if (lin(i+1) .eq. 10) then    ! NEWLINE(10)
              status = append(line2,glob)
          end if
      else if (lin(i) .eq. 99) then     ! CHANGE(99,'c')
          if (lin(i+1) .eq. 10) then    ! NEWLINE(10)
              if (defalt(curln,curln,status) .eq. -2) then ! OK(-2)
                  if (delete(line1,line2,status) .eq. -2) then ! OK(-2)
                      status = append(prevln(line1),glob)
                  end if
              end if
          end if
      else if (lin(i) .eq. 100) then    ! DELETE(100,'d')
          if (ckp(lin,i+1,pflag,status) .eq. -2) then ! OK(-2)
              if (defalt(curln,curln,status) .eq. -2) then ! OK(-2)
                  if (dodel(line1,line2,status) .eq. -2) then ! OK(-2)
                      if (nextln(curln) .ne. 0) then
                          curln = nextln(curln)
                      end if
                   end if
              end if
          end if
      else if (lin(i) .eq. 105) then    ! INSERT(105,'i')
          if (lin(i+1) .eq. 10) then    ! NEWLINE(10)
              status = append(prevln(line2),glob)
          end if
      else if (lin(i) .eq. 61) then     ! PRINTCUR(61,'=')
          if (ckp(lin,i+1,pflag,status) .eq. -2) then ! OK(-2)
              call putdec(line2,1)
              call putc(10)             ! NEWLINE(10)
          end if
      else if (lin(i) .eq. 109) then    ! MOVECOM(109,'m')
          i = i + 1
          if (getone(lin,i,line3,status) .eq. -1) then ! EOF(-1)
              status = -3               ! ERR(-3)
          end if
          if (status .eq. -2) then      ! OK(-2)
              if (ckp(lin,i,pflag,status) .eq. -2) then ! OK(-2)
                  if (defalt(curln,curln,status) .eq. -2) then ! OK(-2)
                      status = move(line3)
                  end if
              end if
          end if
      else if (lin(i) .eq. 115) then    ! SUBSTITUTE(115,'s')
          i = i + 1
          if (optpat(lin,i)) then
              if (getrhs(lin,i,sub,gflag) .eq. -2) then ! OK(-2)
                  if (ckp(lin,i+1,pflag,status) .eq. -2) then ! OK(-2)
                      if (defalt(curln,curln,status) .eq. -2) then ! OK(-2)
                          status = subst(sub,gflag)
                      end if
                  end if
              end if
          end if
      else if (lin(i) .eq. 101) then    ! ENTER(101,'e')
          if (nlines .eq. 0) then
              if (getfn(lin,i,file) .eq. -2) then ! OK(-2)
                  call scopy(file,1,savfil,1)
                  call clrbuf
                  call setbuf
                  status = doread(0,file)
              end if
          end if
      else if (lin(i) .eq. 102) then    ! PRINTFIL(102,'f')
          if (nlines .eq. 0) then
              if (getfn(lin,i,file) .eq. -2) then ! OK(-2)
                  call scopy(file,1,savfil,1)
                  call putlin(savfil,6) ! STDOUT(6)
                  call putc(10)         ! NEWLINE(10)
                  status = -2           ! OK(-2)
              end if
          end if
      else if (lin(i) .eq. 114) then    ! READCOM(114,'r')
          if (getfn(lin,i,file) .eq. -2) then ! OK(-2)
              status = doread(line2,file)
          end if
      else if (lin(i) .eq. 119) then    ! WRITECOM(119'w')
          if (getfn(lin,i,file) .eq. -2) then ! OK(-2)
              if (defalt(1,lastln,status) .eq. -2) then
                  status = dowrit(line1,line2,file)
              end if
          end if
      else if (lin(i) .eq. 112) then    ! PRINT(112 'p')
          if (lin(i+1) .eq. 10) then    ! NEWLINE(10)
              if (defalt(curln,curln,status) .eq. -2) then ! OK(-2)
                  status = doprnt(line1,line2)
              end if 
          end if
      else if (lin(i) .eq. 113) then    ! QUIT(113 'q')
          if ((lin(i+1) .eq. 10) .and.  ! NEWLINE(10)
     1       (nlines .eq. 0) .and. (glob .eq. 0)) then ! NO(0)
              status = -1               ! EOF(-1)
          end if
      ! else status is ERR
      end if

      if ((status .eq. -2) .and. (pflag .eq. 1)) then ! OK(-2) YES(1)
          status = doprnt(curln,curln)
      end if
      docmd = status
      return
      end

コマンドの処理 2 MOVE2016年06月30日 20:30

移動指令moveは文書行の並べ替えを行う。

     /format/m/end/-1p
とすると、最初に見つけた"format"を含む行を "end"を含む行の1行前に移動し、印刷する。

先に示したdocmdの該当部分は、つぎのようになる。

      else if (lin(i) == MOVECOM) {
          i = i + 1
          if (getone(lin,i,line3,status) == EOF)
              status = ERR
          if (status == OK)
              if (ckp(lin,i,pflag,status) == OK)
                  if (defalt(curlin,curln,status) == OK)
                      status = move(line3)
          }

RATFOR版move()はは、以下の通り。

# move.r4 -- move line1 through line2 after line3
      integer function move(line3)
      integer line3

      integer getind,nextln,prevln
      integer k0,k1,k2,k3,k4,k5

      include clines.ri

      if (line1 <= 0 | (line1 <= line3 & line3 <= line2)) then
         move = ERR
      else
          k0 = getind(prevln(line1))
          k3 = getind(nextln(line2))
          k1 = getind(line1)
          k2 = getind(line2)
          call relink(k0,k3,k0,k3)
          if (line3 < line1) {
              curln = line3
              line3 = line3 - (line2 - line1 + 1)
              }
          else
              curln = line3 + (line2 - line1 + 1)
          k4 = getind(line3)
          k5 = getind(nextln(line3))
          call relink(k4,k1,k2,k5)
          call relink(k2,k5,k4,k1)
          move = OK
      end if
      return
      end

WATCOM fortran 77版move()は、以下の通り。

c move.f -- move line1 through line2 after line3
      integer function move(line3)
      integer line3

      integer getind,nextln,prevln
      integer k0,k1,k2,k3,k4,k5

      include clines.fi

      if ((line1 .le. 0)
     1 .or. (line1 .le. line3 .and. line3 .le. line2)) then
         move = -3                      ! ERR(-3)
      else
          k0 = getind(prevln(line1))
          k3 = getind(nextln(line2))
          k1 = getind(line1)
          k2 = getind(line2)
          call relink(k0,k3,k0,k3)
          if (line3 .gt. line1) then
              curln = line3
              line3 = line3 - (line2 - line1 + 1)
          else
              curln = line3 + (line2 - line1 + 1)
          end if
          k4 = getind(line3)
          k5 = getind(nextln(line3))
          call relink(k4,k1,k2,k5)
          call relink(k2,k5,k4,k1)
          move = -2                     ! OK(-2)
      end if
      return
      end