Ratforプリプロセッサー -- 字句解析 ― 2017年05月13日 15:55
Ratforで書かれたプログラムからtokenを切り出すのは、defineやmacroと同様であるが、 引用符の通り扱いに注意が必要である。引用符は、ほとんどの場合ペアで使われ、その間に NEWLINEが入ることはない。この点に配慮する必要がある。
Ratofor版は以下の通り。
# gtoken.f -- get token for ratfor include ratfor.def character function gtoken(lexstr,toksiz) integer toksiz character lexstr(toksiz) character ngetc,type integer i character c include cline.ri while (ngetc(c) != EOF) if ((c != BLANK) & (c != TAB)) break call putbak(c) for(i = 1;i < toksiz-1;i = i +1) { gtoken = type(ngetc(lexstr(i))) if ((gtoken != LETTER) & (gtoken != DIGIT)) break } if (i >= toksiz-1) call synerr('token too long.') if (i > 1) call putbak(lexstr(i)) lexstr(i) = EOS gtoken = ALPHA else if ((lexstr(1) == SQUOTE) | (lexstr(1) == DQUOTE)) for (i = 2;ngetc(lexstr(i)) != lexstr(1)) { if (lexstr(i) == NEWLINE) { call synerr('missing quote.') lexstr(i) = lexstr(1) call putbak(NEWLINE) break } } else if (lexstr(1) == SHARP) { # strip comments while (ngetc(lexstr(1)) != NEWLINE) ; gtoken = NEWLINE } lexstr(i+1) = EOS if (lexstr(1) == NEWLINE) linect = linect + 1 return end
WATCOM Fortran77版は以下の通り。
c gtoken.f -- get token for ratfor include ratfor.def integer*1 function gtoken(lexstr,toksiz) integer toksiz integer*1 lexstr(toksiz) integer*1 ngetc,type integer i integer*1 c include cline.fi while (ngetc(c) .ne. EOF) do if ((c .ne. BLANK) .and. (c .ne. TAB)) then exit end if end while call putbak(c) i = 1 while (i .lt. toksiz-1) do gtoken = type(ngetc(lexstr(i))) if ((gtoken .ne. LETTER) .and. (gtoken .ne. DIGIT)) then exit end if i = i + 1 end while if (i .ge. toksiz-1) then call synerr('token too long.') end if if (i .gt. 1) then call putbak(lexstr(i)) lexstr(i) = EOS gtoken = ALPHA else if (lexstr(1) .eq. SQUOTE .or. lexstr(1) .eq. DQUOTE) then i = 2 while (ngetc(lexstr(i)) .ne. lexstr(1)) do if (lexstr(i) .eq. NEWLINE) then call synerr('missing quote.') lexstr(i) = lexstr(1) call putbak(NEWLINE) exit end if i = i + 1 end while else if (lexstr(1) .eq. SHARP) then ! strip comments while (ngetc(lexstr(1)) .ne. NEWLINE) do ! nothing to do end while gtoken = NEWLINE end if lexstr(i+1) = EOS if (lexstr(1) .eq. NEWLINE) then linect = linect + 1 end if return end
gtoken()の下請けルーチンsynerr()はsyntax errorを出力する。errorは、行番号とともに出力されるが、 行番号linectは、必要なモジュールで共有できるように、共通領域clineにおいている。
synerr()のRatofor版は以下の通り。
# synerr -- report Ratfor syntax error include ratfor.def subroutine synerr(msg) character msg(MAXLINE) character lc(MAXLINE) integer itoc integer junk include cline.ri call remark('error at line.') junk = itoc(linect,lc,MAXLINE) call putlin(lc,ERROUT) call fputc(ERROUT,COLON) call remark(msg) return end
WATCOM Fortran77版は以下の通り。
c synerr -- report Ratfor syntax error include ratfor.def subroutine synerr(msg) character msg(MAXLINE) integer*1 lc(MAXLINE) integer itoc integer junk include cline.fi call remark('error at line.') junk = itoc(linect,lc,MAXLINE) call putlin(lc,ERROUT) call fputc(ERROUT,BLANK) call remark(msg) return end
clineのRatofor版は以下の通り。
# cline.ri common /cline/linect integer linect data linect/1/
WATCOM Fortran77版は以下の通り。
c cline.fi common /cline/linect integer linect data linect/1/
gtoken()で切り出されたtokenは、次のlex()に引き継がれ解析される。 ここでも字句の判定に、lookup()を使用する。
lex()のRatfor版は以下の通り。
# lex.r4- return lexical type of token include ratfor.def character function lex(lexstr) character lexstr(MAXTOK) character gtoken integer alldig,lookup character ltype(2) while (gtoken(lexstr,MAXTOK) == NEWLINE) ; lex = lexstr(1) if (lex == EOF | lex == SEMICOL | lex == LBRACE | lex == RBRACE)) return if (alldig(lexstr)==YES) lex = LEXDIGITS else if(lookup(lexstr,ltype) == YES) lex = ltype(1) else lex = LEXOTHER return end
WATCOM Fortran77版は以下の通り。
c lex.f- return lexical type of token include ratfor.def integer function lex(lexstr) integer*1 lexstr(MAXTOK) integer*1 gtoken integer alldig,lookup integer*1 ltype(2) while (gtoken(lexstr,MAXTOK) .eq. NEWLINE) do ! nothing to do end while lex = lexstr(1) if ((lex .eq. EOF) .or. (lex .eq. SEMICOL) .or. 1 (lex .eq. LBRACE) .or. (lex .eq. RBRACE)) then return end if if (alldig(lexstr)) then lex = LEXDIGITS else if(lookup(lexstr,ltype) .eq. YES) then lex = ltype(1) else lex = LEXOTHER end if return end
lex()の下請けルーチンalldig()は、tokenが数字列か否かを判定する。
alldig()のRatfor版は以下の通り。
# alldig.r4 -- return YES if str is all digis include ratfor.def integer function alldig(s) character s(ARB) character type character i alldig = NO if (s(1) == EOS) return for (i = 1; s(i) != EOS; i = i +1) if (type(s(i)) != DIGIT) return alldig = YES return end
WATCOM Fortran77版は以下の通り。
c alldig -- return YES if str is all digis include ratfor.def integer function alldig(s) integer*1 s(ARB) integer*1 type integer i alldig = NO if (s(1) .eq. EOS) then return end if i = 1 while (s(i) .ne. EOS) do if (type(s(i)) .ne. DIGIT) then return end if i = i + 1 end while alldig = YES return end
OS/2 Warp Server for e-businessの立ち上げ ― 2017年05月22日 17:48
長いこと眠らせておいたPCに、OS/2 Warp Server for e-businessのセットアップをしました。 H/Wの不具合やら勘違いなどで、結構時間がかかりました。最終的に家庭内超私的FTPサーバーとして、 動いています。
最終的なH/W構成は、以下の通り。いずれもこの10年間に入手したものばかりです。
- Mother Board: AOpen i855GMEm-LFS
- CPU: Intel Pentiumn M 2GHz
- Memry: 2GB
- Storages
- E-IDE Primary
- Master: Seagate製 30GB
- Slave: Seagate製 40GB
- E-IDE Secondary
- Master: LG製 GSA-H44N DVDRAM Drive
- Slave: (空き)
- E-IDE Primary
- Removable Media: 3.5Inch 2HD FDD
- Display Adpter: nVIDIA RIVA128 (RAM:4MB)
- Network: RealTek RTL8139 Ethernet Adapter
- Sound: (なし)
- Printer: (なし)
当初、DVDRAM DriveをSlaveに設定していたところ、 不可解な現象に悩まされました(詳細は後述)。
OS/2のインストールは、このバージョンからCD-ROMから起動できるように なりましたので、早速、"インストール"CD-ROMをDVDRAMドライブに入れて 電源を入れると、一見順調に起動するのですが、指示に従いCD-ROMを"ServerPak"に入れ替えて 動き出すと、エラーメッセージを表示しインストールプロセスが停止してしまいます。
原因をつかみたくても、皆目訳がわからない状態なので、インストール用ディスケット 3枚を 作って従来通りのインストール手順を踏むことにしました。 ついでに、IDEDASDをVer.5.02に置き換えて、"Config.sys"を書き換えました。
IDEDASDの置き換え手順は下記のとおりです。
- IDEDASD.EXEを適当なディレクトリーに展開。
- インストール用ディスケット 1のコピーを作成。(D1)
- D1から"README.INS"を削除。
- 展開したIDEDASDのファイルから、"IBM1S506.ADD"と"IBMIDECD.FLT"をD1にコピー。
- "DASD32.DMD"を"OS2DASD.DMD"としてD1にコピー。
- D1にある"Config.sys"を編集。
- 第一行目に"SET COPYFROMFLOPPY=1"を追加。
- 動作確認のため、"IBM1S506.ADD"に"/V"オプションを追加しロード時にメッセージを表示。
SET COPYFROMFLOPPY=1 : basedev=ibm1s506.add /V :
このインストール用ディスケットを使って導入を開始します。
導入開始時点では、すべてのデバイスドライバは、ディスケットから読み取られます。 "IBM1S506.ADD"がロードされた時点で表示されるメッセージを確認すると、 正常にHDDやDVDRAMドライブが検出されていることが確認できました。
一度目のリブート後作業を進めようとすると、CD-ROMを入れるようメッセージが表示されました。 不思議に思い、再度、リブートして"IBM1S506.ADD"のメッセージを確認すると、 DVDRAMドライブを今度は検出しました。しかし、作業を進めリブートを繰り返していくと、 DVDRAMドライブを検出しないことが多々見受けられました。
"IBM1S506.ADD"以外にもSCSI用デバイスドライバがロードされますが、これらがH/Wの 誤検出をしてるのかと考え、"Config.sys"のSCSI用デバイスドライバをロードする部分をREM化して みましたが、状況は変わりません。
"Config.sys"の変更点は以下の通りです。
: REM basedev=aha152x.add REM basedev=aha154x.add REM basedev=aha164x.add REM basedev=aha174x.add REM basedev=aic7770.add REM basedev=aic7870.add REM basedev=aic78u2.add REM basedev=dpt20xx.add REM basedev=flashpt.add REM basedev=ql10os2.add REM basedev=ql40os2.add REM basedev=ql510.add :
となると、悪いのはDVDRAMドライブではないかと、代替え品をと考え、手持ちのCD-ROMドライブを あてがってみたのですが、なにぶん、長期保存品につき不良品になっていました。 残るは、DVDRAMドライブを設定をMASTERにすることぐらいです。先に変更した"Config.sys"を元に 戻し、ついでに"OS2CDROM.DMD"に"/V"オプションをつけロード時にメッセージが表示されるようにしました。
: device=\os2cdrom.dmd /V :
今度は、リブート後もDVDRAMドライブが確実に検出されるようになり、インストール作業が順調に 進み、完了することができました。
ほかのマシンでは、他社のDVDROMドライブだがSLAVEの設定で問題なく動作しているので、DVDRAMに 問題があり、動作が不安定になったものと思われます。
次に、Display Adpterを"On Board VGA"から"nVIDIA RIVA128"に変更しました。
最終的に、以下のFIXをあてて、導入作業を完了としました。
導入順に示します。FIXは"ftp.boulder.ibm.com"から入手しました。
- Base Operating System
- IC24998.EXE
- JFS0905.ZIP
- XRJE001
- JFS1009.ZIP
- XRJE002
- TCP/IP
- IC22633
- IC27255
- IC27869
- UN_2101
- MPTS
- WR_8650
FIXを導入するに当たり、下記のツールを使っています。VFDiskは"hobbes.nmsu.edu"から、 その他は"ftp.boulder.ibm.com"から入手できます。
- VFDisk -- 仮想ディスケットドライバー
- Loaddskf -- ディスケット作成ツール
- CSJ144 -- コレクティブサービスツール
Ratforプリプロセッサー -- 構文解析 ― 2017年05月25日 16:50
Ratforで書かれたプログラム文は、parse()で解析され、lex()が返す綴り別に それがコードの始まりの時は、コード生成ルーチンを呼び出し、スタックに綴りの種類と 名札が積まれる。コードの終わりの時は、unstak()が呼ばれスタックから取りおろしをします。 綴りは、defineやmacroのように、initkw()でテーブルにセットします。
parse()のRatofor版は以下の通り。
# parse.r4 -- parse Ratfor source program include ratfor.def subroutine parse character lexstr(MAXTOK) character lex, token integer lab,sp integer labval(MAXSTACK) character lextyp(MAXSTACK) call initkw # install keywords in table sp = 1 lextyp(1) = EOF for (token = lex(lexstr); token != EOF; token = lex(lexstr) ) { if (token == LEXIF) call ifcode(lab) else if (token == LEXDO) call docode(lab) else if (token == LEXWHILE) call whilec(lab) else if (token == LEXFOR) call forcod(lab) else if (token == LEXREPEAT) call repcod(lab) else if (token == LEXUNTIL) { if (lextyp(sp) == LEXREPEAT) call synerr('illegal until.') } else if (token == LEXSTRING) call strngc else if (token == LEXDIGITS) call labelc(lexstr) else if (token == LEXELSE) { if (lextyp(sp) == LEXIF) call elseif(labval(sp)) else call synerr('illegal else.') } if (token == LEXIF | token == LEXELSE | token == LEXWHILE | token == LEXDO | token == LEXDIGITS | token == LBRACE | token == LEXFOR | token == LEXREPEAT) { sp = sp + 1 if (sp > MAXSTACK) call synerr('stack overflow in paser.') lextyp(sp) = token labval(sp) = lab } else } if (token == RBRACE) if (lextyp(sp) == LBRACE) sp = sp - 1 else call synerr('illegal right brace.') else if (token == LEXOTHER) call otherc(lexstr) else if (token == LEXBREAK | token == LEXNEXT) call brknxt(sp,lextyp,labval,token) token = lex(lexstr) # peek at next token call pbstr(lexstr) call unstak(sp,lextyp,labval,token) } } if (sp != 1) call synerr('unexpected EOF.') return end
WATCOM Fortran77版は以下の通り。
c parse.f -- parse Ratfor source program include ratfor.def subroutine parse integer*1 lexstr(MAXTOK) integer*1 lex,lextyp(MAXSTACK),token integer lab,labval(MAXSTACK),sp call initkw ! install keywords in table sp = 1 lextyp(1) = EOF token = lex(lexstr) while (token .ne. EOF) do if (token .eq. LEXIF) then call ifcode(lab) else if (token .eq. LEXDO) then call docode(lab) else if (token .eq. LEXWHILE) then call whilec(lab) else if (token .eq. LEXFOR) then call forcod(lab) else if (token .eq. LEXREPEAT) then call repcod(lab) else if (token .eq. LEXUNTIL) then if (lextyp(sp) .ne. LEXREPEAT) then call synerr('illegal until.') end if else if (token .eq. LEXSTRING) then call strngc else if (token .eq. LEXDIGITS) then call labelc(lexstr) else if (token .eq. LEXELSE) then if (lextyp(sp) .eq. LEXIF) then call elseif(labval(sp)) else call synerr('illegal else.') end if end if if ((token .eq. LEXIF) .or. (token .eq. LEXELSE) .or. 1 (token .eq. LEXWHILE) .or. (token .eq. LEXDO) .or. 2 (token .eq. LEXDIGITS) .or. (token .eq. LBRACE) .or. 3 (token .eq. LEXFOR) .or. (token .eq. LEXREPEAT)) then sp = sp + 1 if (sp .gt. MAXSTACK) then call synerr('stack overflow in paser.') end if lextyp(sp) = token labval(sp) = lab else if (token .eq. RBRACE) then if (lextyp(sp) .eq. LBRACE) then sp = sp - 1 else call synerr('illegal right brace.') end if else if (token .eq. LEXOTHER) then call otherc(lexstr) else if (token .eq. LEXBREAK .or. token .eq. LEXNEXT) then call brknxt(sp,lextyp,labval,token) end if token = lex(lexstr) ! peek at next token call pbstr(lexstr) call unstak(sp,lextyp,labval,token) end if token = lex(lexstr) end while if (sp .ne. 1) then call synerr('unexpected EOF.') end if return end
initkw()は、見出し語をinstal()を使って登録します。
Ratofor版は以下の通り。
# initkw.f -- install Ratfor keyword include ratfor.def subroutine initkw string(ifst,"if") character iftyp(2) data iftyp(1)/LEXIF/ data iftyp(2)/EOS/ string(elsest,"else") character elstyp(2) data elstyp(1)/LEXELSE/ data elstyp(2)/EOS/ string(whilst,"while") character whityp(2) data whityp(1)/LEXWHILE/ data whityp(2)/EOS/ string(forst,"for") character fortyp(2) data fortyp(1)/LEXFOR/ data fortyp(2)/EOS/ string(repest,"repeat") character reptyp(2) data reptyp(1)/LEXREPEAT/ data reptyp(2)/EOS/ string(untist,"until") character unttyp(2) data unttyp(1)/LEXUNTIL/ data unttyp(2)/EOS/ string(dost,"do") character dotyp(2) data dotyp(1)/LEXDO/ data dotyp(2)/EOS/ string(breast,"break") character bretyp(2) data bretyp(1)/LEXBREAK/ data bretyp(2)/EOS/ string(nextst,"next") character nextyp(2) data nextyp(1)/LEXNEXT/ data nextyp(2)/EOS/ integer*1 strtyp(2) data strtyp(1)/LEXSTRING/ data strtyp(2)/EOS/ call instal(ifst,iftyp) call instal(elsest,elstyp) call instal(whilst,whityp) call instal(forst,fortyp) call instal(repest,reptyp) call instal(untist,unttyp) call instal(dost,dotyp) call instal(breast,bretyp) call instal(nextst,nextyp) call instal(strst,strtyp) return end
WATCOM Fortran77版は以下の通り。
c initkw.f -- install Ratfor keyword include ratfor.def subroutine initkw string(ifst,"if") integer*1 iftyp(2) data iftyp(1)/LEXIF/ data iftyp(2)/EOS/ string(elsest,"else") integer*1 elstyp(2) data elstyp(1)/LEXELSE/ data elstyp(2)/EOS/ string(whilst,"while") integer*1 whityp(2) data whityp(1)/LEXWHILE/ data whityp(2)/EOS/ string(forst,"for") integer*1 fortyp(2) data fortyp(1)/LEXFOR/ data fortyp(2)/EOS/ string(repest,"repeat") integer*1 reptyp(2) data reptyp(1)/LEXREPEAT/ data reptyp(2)/EOS/ string(untist,"until") integer*1 unttyp(2) data unttyp(1)/LEXUNTIL/ data unttyp(2)/EOS/ string(dost,"do") integer*1 dotyp(2) data dotyp(1)/LEXDO/ data dotyp(2)/EOS/ string(breast,"break") integer*1 bretyp(2) data bretyp(1)/LEXBREAK/ data bretyp(2)/EOS/ string(nextst,"next") integer*1 nextyp(2) data nextyp(1)/LEXNEXT/ data nextyp(2)/EOS/ integer*1 strst(7) data strst(1)/LETs/ data strst(2)/LETt/ data strst(3)/LETr/ data strst(4)/LETi/ data strst(5)/LETn/ data strst(6)/LETg/ data strst(7)/EOS/ integer*1 strtyp(2) data strtyp(1)/LEXSTRING/ data strtyp(2)/EOS/ call instal(ifst,iftyp) call instal(elsest,elstyp) call instal(whilst,whityp) call instal(forst,fortyp) call instal(repest,reptyp) call instal(untist,unttyp) call instal(dost,dotyp) call instal(breast,bretyp) call instal(nextst,nextyp) call instal(strst,strtyp) return end
unstak()は、スタックに最後に積まれた綴りに応じた構文の終わりのコードを生成し、 スタックから取り下ろします。
unstak()のRatofor版は以下の通り。
# unstack.f -- unstack at end of statment include ratfor.def subroutine unstak(sp,lextyp,labval,token) integer sp integer labval(MAXSTACK) character token character lextyp(MAXSTACK) for ( ; sp > 1; sp = sp -1) { if (lextyp(sp) == LBRACE) break if ((lextyp(sp) == LEXIF) & (token == LEXELSE)) break if (lextyp(sp) == LEXIF) call outcon(labval(sp)) else if (lextyp(sp) == LEXELSE) { if (sp > 2) sp = sp - 1 call outcon(labval(sp)+1) } else if (lextyp(sp) == LEXDO) call dostat(labval(sp)) else if (lextyp(sp) == LEXFOR) call forsta(labval(sp)) else if (lextyp(sp) == LEXREPEAT) call repats(labval(sp)) else if (lextyp(sp) == LEXWHILE) call whiles(labval(sp)) } return end
WATCOM Fortran77版は以下の通り。
c unstack.f -- unstack at end of statment include ratfor.def subroutine unstak(sp,lextyp,labval,token) integer labval(MAXSTACK),sp integer*1 lextyp(MAXSTACK),token while (sp .gt. 1) do if (lextyp(sp) .eq. LBRACE) then exit end if if ((lextyp(sp) .eq. LEXIF) .and. (token .eq. LEXELSE)) then exit end if if (lextyp(sp) .eq. LEXIF) then call outcon(labval(sp)) else if (lextyp(sp) .eq. LEXELSE) then if (sp .gt. 2) then sp = sp - 1 end if call outcon(labval(sp)+1) else if (lextyp(sp) .eq. LEXDO) then call dostat(labval(sp)) else if (lextyp(sp) .eq. LEXFOR) then call forsta(labval(sp)) else if (lextyp(sp) .eq. LEXREPEAT) then call repats(labval(sp)) else if (lextyp(sp) .eq. LEXWHILE) then call whiles(labval(sp)) end if sp = sp - 1 end while return end
Ratforのメインプリグラムはとても簡単です。
Ratofor版は以下の通り。
# ratfor.r4 -- main program for Ratfor program ratfor call initfile call parse stop end
WATCOM Fortran77版は以下の通り。
c ratfor.f -- main program for Ratfor program ratfor call initfile call parse stop end
最近のコメント