edit -- 全体構造 ― 2015年11月21日 09:00
editは、非常に大きなプログラムで、なおかつ、問題が起きた時に黙って死んでしまうような、 弱いプログラムであってはならない。信頼性が必要なプログラムであることが大事である。
editへの入力は指令行である。指令行は、以下のようになっている。
行1,行2 指令 追加情報ここで、「行1」、「行2」、「追加情報」は省略可能である。したがって、editの主たるループは、 下記のようになる。
while (getlin(lin,STDIN) != EOF { linから行番号を取り出す if ( 状況がOK ) 指令を実行 }指令を実行する部分では、指令別に多方向へ分岐して処理を進めることになる。これらの処理も 含めて、editの 各部分では、関数の値と、引数statusの両方に状況を返すようにしてある。うまくいったときは OK、まずいことがあればERRを下位のルーチンで入力を 読みつくしてしまった場合は、EOFをそれぞれ返すことになっている。
共通の制御情報は、clinesにある。
RATFOR版は、以下の通り。
# clines.ri common /clines/line1,line2,nlines,curln,lastln integer line1 # first line number integer line2 # second line number integer nlines # numberif line numbers specified integer curln # current line: value of dot integer lastln # last line: value of $
WATCOM Fortran77版は以下の通り。
c clines.fi common /clines/line1,line2,nlines,curln,lastln integer line1 ! first line number integer line2 ! second line number integer nlines ! numberif line numbers specified integer curln ! current line: value of dot integer lastln ! last line: value of $
指令行から、行番号を取り出すのは、getlst()が、getone()を呼び出しながら、 行う。行番号は、clinesのline1、line2に、入る。
RATFOR版のgetlst()は、次の通り。
# getlst.r -- collect line numbers (if any) at lin(i), increment i integer function getlst(lin,i,status) character lin(MAXLINE) integer i,status integer getone,min, num include clines.ri line2 = 0 for (nlines = 0; getone(lin,i,num,status) == OK; ) { line1 = line2 line2 = num nlines = nlines + 1 if (lin(i) != COMMA & lin(i) != SEMICOL) break if (lin(i) == SEMICOL) then curln = num i = i + 1 } nlines = min(nlines,2) if (nlines == 0) line2 = curln if (nlines <= 1) line1 = line2 if (status != ERR) status = OK getlst = status return end
WATCOM Fortran77版は下記の通り。
c getlst.f -- collect line numbers (if any) at lin(i), increment i integer function getlst(lin,i,status) integer*1 lin(82) ! MAXLINE(82) integer i,status integer getone,min, num include clines.fi line2 = 0 nlines = 0 while (getone(lin,i,num,status) .eq. -2) do line1 = line2 line2 = num nlines = nlines + 1 if ((lin(i) .ne. '2c'x) .and. (lin(i) .ne. '3b'x)) then ! COMMA(2cx '.') SEMICIL(3bx ';') exit end if if (lin(i) .eq. '3b'x) then ! SEMICOL(3bx ';') curln = num end if i = i + 1 end while nlines = min(nlines,2) if (nlines .eq. 0) then line2 = curln end if if (nlines .le. 1) then line1 = line2 end if if (status .ne. -3) then ! ERR(-3) status = -2 ! OK(-2) end if getlst = status return end
getone()では、行番号を一つ評価する。
RATFOR版は以下の通り。
# getone.r -- evaluate one line number expression integer function getone(lin,i,num,status) character lin(MAXLINE) integer i,num,status integer getnum integer istart,mul,pnum include clines.ri istart = i num = 0 call skipbl(lin,i) if (getnum(lin,i,num,status) == OK) # first term repeat { # + or - terms call skipbl(lin,i) if (lin(i) != PLUS & lin(i) != MINUS) status = EOF beak if (lin(i) .eq. PLUS) mul = +1 else mul = -1 i = i + 1 call skipbl(lin,i) if (getnum(lin,i,pnum,status) == OK) num = num + mul * pnum if (status == EOF) status = ERR } until (status != OK) if (num < 0 | num > lastln) status = ERR if (status == ERR) getone = ERR else if (i <= istart) getone = EOF else getone = OK status = getone return end
WATCOM Fortran77版は以下の通り。
c getone.f -- evaluate one line number expression integer function getone(lin,i,num,status) integer*1 lin(82) ! MAXLINE(82) integer i,num,status integer getnum integer istart,mul,pnum include clines.fi istart = i num = 0 call skipbl(lin,i) if (getnum(lin,i,num,status) .eq. -2) then ! OK(-2) loop call skipbl(lin,i) if ((lin(i) .ne. '2b'x) .and. (lin(i) .ne. '2d'x)) then ! PLUS(2bx '+') MINUS(2dx '-') status = -1 ! EOF(-1) exit end if if (lin(i) .eq. '2b'x) then mul = +1 else mul = -1 end if i = i + 1 call skipbl(lin,i) if (getnum(lin,i,pnum,status) .eq. -2) then ! OK(-2) num = num + mul * pnum end if if (status .eq. -1) then ! EOF(-1) status = -3 ! ERR(-3) end if until (status .ne. -2) ! OK(-2) end if if ((num .lt. 0) .or. (num .gt. lastln)) then status = -3 ! ERR(-3) end if if (status .eq. -3) then getone = -3 ! ERR(-3) else if (i .le. istart) then getone = -1 ! EOF(-1) else getone = -2 ! OK(-2) end if status = getone return end
下請けルーチンskipbl()は、空白文字をまたぎ越す。
RATFOR版は下記の通り。
# skipbl.r4 -- skip blank and tabs at lin(i)... subroutine skipbl(lin,i) character lin(ARB) integer i while (lin(i) == BLANK | lin(i) == TAB) i = i + 1 return end
WATCOM Fortran77版は下記の通り。
c skipbl.for -- skip blank and tabs at lin(i)... subroutine skipbl(lin,i) integer*1 lin(*) ! ARB(*) integer i while ((lin(i) .eq. 32) .or. (lin(i) .eq. 9)) do ! BLANK(32) TAB(9) i = i + 1 end while return end
getnum()は、項1つを行番号に変換する。
RATFOR版は以下の通り。
# getnum.r -- convert one term to line number integer function getnum(lin,i,pnum,status) character lin(ARB) integer i,pnum,status integer optpat integer ctoi,iindex,ptscan string digits='0123456789' include cpat.ri include clines.ri getnum = OK if (iindex(digits,lin(i)) > 0) pnum = ctoi(lin,i) i = i - 1 else if (lin(i) == CURLINE) pnum = curln else if (lin(i) == LASTLINE) pnum = lastln else if (lin(i) == SCAN | lin(i) == BACKSCAN) if (optpat(lin,i) == ERR) getnum = ERR else if (lin(i) == SCAN) getnum = ptscan(FORWARD,pnum) else getnum = ptscan(BACKWARD,pnum) else getnum = EOF end if if (getnum == OK) i = i + 1 # point at next character to be examined status = getnum return end
WATCOMM Fortran77版は以下の通り。
c getnum.f -- convert one term to line number integer function getnum(lin,i,pnum,status) integer*1 lin(*) ! ARB(*) integer i,pnum,status integer optpat integer ctoi,iindex,ptscan integer*1 digits(11) data digits/'0','1','2','3','4','5','6','7','8','9',-2/ include cpat.fi include clines.fi getnum = -2 ! OK(-2) if (iindex(digits,lin(i)) .gt. 0) then pnum = ctoi(lin,i) i = i - 1 else if (lin(i) .eq. '2e'x) then ! CURLINE(2ex '.') pnum = curln else if (lin(i) .eq. '24'x) then ! LASTLINE(24x '$') pnum = lastln else if ((lin(i) .eq. '2f'x) .or. (lin(i) .eq. '5c'x)) then ! SCAN(2fx '/') BACKSCAN(5cx '\') if (.not. optpat(lin,i)) then ! error getnum = -3 ! ERR(-3) else if (lin(i) .eq. '2f'x) then ! SCAN(2fx '/') getnum = ptscan(1,pnum) ! FORWARD(1) else getnum = ptscan(-1,pnum) ! BACKWARD(-1) end if else getnum = -1 ! EOF(-1) end if if (getnum .eq. -2) then i = i + 1 end if status = getnum return end
最近のコメント