LoginSignup
7

More than 1 year has passed since last update.

割と簡単に '標準 Pascal' を試してみたい

Last updated at Posted at 2019-03-05

はじめに

Delphi を使っていて、何が 標準 Pascal (Standard Pascal) に準拠していて何が準拠していないのかふと知りたくなることがあります。ISO/IEC 7185 の仕様を読めばいいのですが、実際にコードを実行して試したい事がよくあります。

そんな時は ideoneGNU Pascal (gpc) を使ったり、同じく Free Pascal (fpc)標準 Pascal 互換モード にしてみたりするのですが、これらは純粋な標準 Pascal ではないので、場合によっては検証にならなかったりします。

純粋な '標準 Pascal' を求めて

Windows 環境で最も簡単に実行できる標準 Pascal は Scott A. Moore 氏が書いた (改修した) Pascal-P5 だと思われます (P4 まではサブセット)。

PASCAL-P シリーズは P-CODE コンパイラです。PCOM / PINT の 2 つのコマンドがあり、PCOM がソースコードを中間ファイル形式にコンパイルし、それを PINT が実行します。PCOM がコンパイラで PINT がインタプリタという訳です。

より正確に言えば、PCOM が Pascal ソースコードを中間ファイル形式 (疑似アセンブラソース) に変換し、PINT が 中間ファイルをアセンブルして疑似機械語に変換したもの (メモリ上に生成) を実行しています。

なので、理屈的には PINT さえ移植できればどこでもプログラムを実行できます。え? Java っぽい? え? .NET っぽい? え? VB っぽい?そうですか...

■ ISO 標準 Pascal を取り巻く状況

Pascal-P5 は ISO 標準 Pascal の仕様でコンパイルされる前提になっていますが、現在では ISO 標準 Pascal を準備する事自体が難しい状況になっています。ISO 標準 Pascal を試すために ISO 標準 Pascal が必要という「鶏が先か卵が先か」という状況です。

GNU Pascal (gpc) は ISO 標準 Pascal の仕様を含んでいますが、最近の Linux のパッケージには含まれていないことが多く、Windows 環境への導入も面倒です。

Free Pascal (fpc) はマルチプラットフォームで導入も簡単なのですが、Turbo Pascal 寄りであり、ISO 標準 Pascal 互換に近づけるには {$mode ISO} を指定してコンパイルするか、コンパイルスイッチ -Miso を付ける必要があります。

幸い、Pascal-P5 のアーカイブには Windows 用の実行可能ファイル (EXE) が含まれているため、Windows 環境ならば割と簡単に ISO 標準 Pascal を試すことができます 1

■ Window で Pascal-P5 を動かす

環境設定

PASCAL-P5 のアーカイブを解凍したら、bin フォルダにある PCOM.EXEPINT.EXE を適当な場所にコピーします。これが PASCAL-P5 の本体です 2

さて、PCOM は prd という名前のファイルをソースコードとみなし、コンパイルして prr という中間形式ファイルを出力します。そして PINT は prd という名前のファイルを中間形式ファイルとみなして実行します...どちらも入力ファイルが prd で出力ファイルが prr です。名前決め打ちなんですよ、面倒ですね。

これを簡単にするバッチファイルもアーカイブの bin フォルダにあるのですが、何故かバッチファイルに cp や mv が使われていて Cygwin がないと動作しません。

スクリプト (バッチ) ファイル

面倒なので Cygwin が不要なようにバッチファイルを書きました。以下の 4 つのファイルを pcom.exe / pint.exe と同じ場所に保存してください。

・setpath.bat
カレントディレクトリを環境変数 PATH に設定するバッチファイルです。

setpath.bat
@echo off
cls
set PATH=%CD%;%PATH%
echo %PATH%

・compile.bat
ソースファイルをコンパイルして中間形式ファイルを出力するバッチファイルです。

compile.bat
@echo off
cls

if not "%1"=="" goto paramok
echo *** Error: Missing parameter
goto exit

:paramok
if exist "%1.pas" goto fileexists
if exist "%1.dpr" goto fileexists
echo *** Error: Missing %1.pas file
goto exit

:fileexists
if "%2"=="" goto continue
if exist "%2" goto continue
echo *** Error: Missing %2 input file
goto exit

:continue
echo.
echo Compiling and running %1
echo.
if exist "%1.pas" copy %1.pas prd > nul
if exist "%1.dpr" copy %1.dpr prd > nul
pcom
move prr %1.p5 > nul

:stop
if exist prd del prd

:exit

・run.bat
中間形式ファイルを解釈して実行するバッチファイルです。

run.bat
@echo off
cls

if not "%1"=="" goto paramok
echo *** Error: Missing parameter
goto exit

:paramok
if exist "%1.p5" goto fileexists
echo *** Error: Missing %1.p5 file
goto exit

:fileexists
if not "%2"=="" goto useinputfile
copy %1.p5 prd > nul
goto run

:useinputfile
rem The input file, if it exists, gets put on the end of the intermediate
echo ? >> %1.p5
type %1.p5 %2 > prd

:run
pint
if "%3"=="" goto stop
copy prr %3 > nul

:stop
if exist prd del prd
if exist prr del prr

:exit

・p5.bat
ソースコードファイルをコンパイルして実行するバッチファイルです。

p5.bat
@echo off
cls

if not "%1"=="" goto paramok
echo *** Error: Missing parameter
goto stop

:paramok
if exist "%1.pas" goto fileexists
if exist "%1.dpr" goto fileexists
echo *** Error: Missing %1.pas file
goto stop

:fileexists
if "%2"=="" goto continue
if exist "%2" goto continue
echo *** Error: Missing %2 input file
goto stop

:continue
echo.
echo Compiling and running %1
echo.
if exist "%1.pas" copy %1.pas prd > nul
if exist "%1.dpr" copy %1.dpr prd > nul
pcom
move prr %1.p5  > nul
if not "%2"=="" goto useinputfile
copy %1.p5 prd  > nul
goto run

:useinputfile
rem The input file, if it exists, gets put on the end of the intermediate
echo ? >> %1.p5
type %1.p5 %2 > prd

:run
pint
if "%3"=="" goto stop
copy prr %3 > nul

:stop
if exist prd del prd
if exist prr del prr

:exit

PASCAL-P5 の使い方 (Windows)

まず、サンプルプログラムを用意します。アーカイブの sample-programs フォルダにもサンプルがありますが、今回は FizzBuzz を用意してみました。

FizzBuzz.pas
program FizzBuzz(output);
var
  i: Integer;
begin
  for i:=1 to 100 do
    begin
      if ((i mod 3) + (i mod 5)) = 0 then
        Writeln('Fizz Buzz')
      else if (i mod 3) = 0 then
        Writeln('Fizz')
      else if (i mod 5) = 0 then
        Writeln('Buzz')
      else
        Writeln(i);
    end;
end.

まず、PASCAL-P5 (とバッチファイル) を格納したフォルダへ移動します。
image.png
アドレスバーに CMD と入力し〔Enter〕キーを押し、
image.png
カレントディレクトリでコマンドプロンプトを開きます。
image.png
先程の FizzBuzz.pas が違うフォルダにあるのであれば setpath を実行して PASCAL-P5 にパスを通しておきます。
image.png
compile fizzbuzz としてコンパイルします。ここでの拡張子の入力は不要ですが、ソースファイル名は *.pas である必要があります 3
image.png
正しくコンパイルされると fizzbuzz.p5 ファイルが生成されます。これが中間形式ファイルです。
image.png
run fizzbuzz として実行します。拡張子は不要です。一旦中間形式ファイルができてしまえば、実行の都度コンパイルする必要はありません。
image.png
p5 fizzbuzz とすると、コンパイルと実行を連続して行います。
image.png

外部ファイルの扱い方

PASCAL-P5 では、任意の外部ファイルを扱えませんが、2 つの外部テキストファイルを扱う事ができます。但し理屈的に、プログラムで書き出したファイルを同じプログラムで読み込めないという制約があります。

外部ファイル 説明
prd 読み込み専用の外部ファイル
prr 書き込み専用の外部ファイル

PASCAL-P5 のコンパイラである PCOM は、次のような動作になっています。

  • prd という名前のファイルをソースファイル (Pascal) として扱う。
  • prr という名前でコンパイルされた中間ファイルを出力する。

PASCAL-P5 のインタプリタである PINT は、次のような動作になっています。

  • prd という名前のファイルを中間形式ファイルとして扱う。
  • prr という名前で出力ファイルを出力する。

少しややこしいのですが、コンパイラ (PCOM) もインタプリタ (PINT) も入力ファイル prd と、出力ファイル prr という 2 つの外部ファイルしか扱えないという事です。

インタプリタ実行用バッチファイル run.bat は外部ファイルを扱えるようになっています。

run.bat "プログラム (中間形式ファイル)" <"入力ファイル" <"出力ファイル">>

入力ファイルがある場合、それを中間形式ファイルの後ろにマージします。

・ファイル入力

例えば次のファイルがあったとします。

hello.txt
Hello,world.
BlaisePascal

次のプログラムは入力ファイルを標準出力に出力します。

ReadFile.pas
program ReadFile(output, prd);
var
  C: Char;
begin
  Reset(prd);
  while not Eof(prd) do
    begin
      while not Eoln(prd) do
        begin
          Read(prd, C);
          Write(C);
        end;
      Readln(prd);
      Writeln;  
    end;
end.

次のようにすると入力ファイル hello.txt を受け取ります。

run ReadFile hello.txt

但し、中間ファイルとマージしているため、中間ファイルの内容も表示してしまいます。
image.png
バッチファイルは中間ファイルと入力ファイルをマージする時に ? を挟み込んでいますから、これを目印に中間ファイルを読み飛ばす事は可能です。

ReadFile
program ReadFile(output, prd);
label
  1;
var
  C: Char;
begin
  Reset(prd);
  { Skip Intermediate File }
  while not Eof(prd) do
    begin
      Read(prd, C);
      if C = '?' then
        begin
          Readln(prd);
          goto 1;  
        end;  
    end;   
1:
  while not Eof(prd) do
    begin
      while not Eoln(prd) do
        begin
          Read(prd, C);
          Write(C);
        end;
      Readln(prd);
      Writeln;  
    end;
end.

今度は入力ファイルだけが処理されています。
image.png

・ファイル出力

次のプログラムはテキストファイルを出力します。

WriteFile.pas
program WriteFile(prr);
begin
  Rewrite(prr);
  Writeln(prr, 'Hello,world.');
  Writeln(prr, 'BlaisePascal');
end.

次のようにすると入力ファイルなし (NUL) で、hello.txt を出力します。

run WriteFile NUL hello.txt

image.png

hello.txt
Hello,world.
BlaisePascal

■ pcom と pint をソースコードからビルドする際の注意事項

独自ビルドする場合には、doc フォルダにある the_p5_compiler.pdf に軽く目を通しておいてください。本記事の手順はドキュメント記載の手順と異なる場合があります。

コンパイルが通り、pcom を単独で実行した際に、次のような表示になるのであれば、後述するソースコードの修正が必要です。

P5 Pascal compiler vs. 1.3
Pascal-P5 complies with the requirements of level 0 of ISO/IEC 7185.

i
i Pascal intermediate file Generated by P5 Pascal compiler vs. 1.3
i
o a-b-c+d+e-f-g-h-i-j-k-l+m-n-o-p-q-r+s-t-u+v+w-x-y-z-

i i i o... と続くこのファイルはコンパイラが吐く中間形式ファイルで、これをファイルではなく標準出力 (画面) に出力してしまっています。

最新版 (v1.4) のソースは GPC 以外でコンパイルする事が困難になっています (GPC も一緒に置いてありますが...)。

v1.3 のアーカイブが DL できなくなってしまったようなので、https://ayera.dl.sourceforge.net/project/pascalp5/pascal-p5.tar.gz を https://ht-deko.com/software/pascal-p5.tar.gz にミラーしておきました。

FPC でビルドする/した際の注意点

FPC のバージョンによっては EOF() の解釈が標準 Pascal と異なるため、2 つの問題が発生します。

  1. ソースコードのピリオドの後に任意の 1 バイトが必要。
  2. PINT が End of file のエラーを出力する事がある。

前者は次のコードでエラーが出ます。

hello.pas
program Hello(Output);
begin
  Writeln('Hello, world.');
end.
Error numbers in listing:
-------------------------
  6  Illigal symbol
 22  '.' expected

ピリオドの後に任意の一文字があれば問題を回避できますので、ピリオドの後で改行しておくといいでしょう。CP/M ファイルのように、ファイル終端として 0x1A を追加してもいいと思います。

後者は PINT.PAS を一部書き換える必要があります。2332 行付近にある次のコードを

pint.pas
                              { FPC has an error where it indicates EOF 1 byte 
                                before the end of the file. A workaround is to
                                comment the EOF check out, but note that this
                                is not permanent, since it compromises error
                                checking. }
                              if eof(bfiltable[fn]) then
                                errori('End of file              ');

コメントアウトします。

pint.pas
                              { FPC has an error where it indicates EOF 1 byte 
                                before the end of the file. A workaround is to
                                comment the EOF check out, but note that this
                                is not permanent, since it compromises error
                                checking. }
{
                              if eof(bfiltable[fn]) then
                                errori('End of file              ');
}

Windows 11 の WSL2 (Ubuntu 20.04.3 LTS) にインストールした fpc (3.0.4+dfsg-23 [2019/11/25] for x86_6) では EOF() の問題は発生しませんでした。

現状 (2021/10 現在) では、Windows / macOS / Linux で修正箇所は同一になっていると思います。

■ Windows の場合 (fpc でコンパイルする場合)

Windows 環境で Free Pascal (fpc) を用いてソースコードから Pascal-P5 をビルドする手順です。

Windows 10 1803 以降で作業する事を想定しています。FreePascal (または Lazarus) は適当な場所にインストールしておいてください。

環境設定

アーカイブを DL して解凍しておきます。

C:\> mkdir c:\tmp
C:\> cd C:\tmp
C:\tmp> curl -OL https://ht-deko.com/software/pascal-p5.tar.gz
C:\tmp> tar -zxvf pascal-p5.tar.gz
C:\tmp> cd Pascal-p5\source
C:\tmp\Pascal-p5\source> 

コンパイル

アーカイブに最初から入っているバイナリと同じ挙動にするにはソースコードの修正が必要なようです。修正点は macOS の場合と同じです。

note: 当方の環境には Lazarus がインストールされており、それに含まれる fpc をコンパイルに使ったのですが、バージョンは 3.0.4 [2018/5/19] でした。{$mode ISO} は効くようですが、外部ファイルとの関連付けに assign() が必要な感じです。
image.png
修正が終わったら fpc.exe にパスを通します。

C:\tmp\Pascal-p5\source> set path=<fpc.exe のある場所>;%PATH%

コンパイルします。

C:\tmp\Pascal-p5\source> fpc -Miso -v0 pcom.pas
C:\tmp\Pascal-p5\source> fpc -Miso -v0 pint.pas

pcom.exepint.exe が生成されていると思うので、これをコピーして使います。

■ Windows の場合 (gpc でコンパイルする場合)

Windows 環境で GNU Pascal (gpc) を用いてソースコードから Pascal-P5 をビルドする手順です。

MinGW と GPC の環境設定を行います。『Pascal 日和』 さんの記事を参考にしてください。

環境設定

アーカイブを DL して解凍しておきます。

C:\> mkdir c:\tmp
C:\> cd C:\tmp
C:\tmp> curl -OL https://ht-deko.com/software/pascal-p5.tar.gz
C:\tmp> tar -zxvf pascal-p5.tar.gz
C:\tmp> cd Pascal-p5

コンパイル

設定が正しく完了していれば、ドキュメントにあるように、

C:\tmp\Pascal-p5> setpath
C:\tmp\Pascal-p5> configure
C:\tmp\Pascal-p5> make

と実行するだけです。実行ファイルは Pascal-p5\bin フォルダに生成されます。

最新版のソースだと cc.exe がなくて spew.c がコンパイルできないかもしれません。spew.exe が不要なら放置で、必要なら MinGW の bin フォルダにある gcc.exe をコピーして cc.exe にリネームしたものを置いておくといいでしょう。

■ macOS の場合 (fpc でコンパイルする場合)

macOS 環境で Free Pascal (fpc) を用いてソースコードから Pascal-P5 をビルドする手順です。

事前に Xcode はインストールされているものとします。当方の環境は macOS High Sierra (10.13.6) / Mac Mini (Mid 2011) です。

環境設定

まずはパッケージャ Homebrew を導入します。

サイトの説明にあるように、ターミナルで以下のスクリプトを実行します。

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Homebrew の導入が終わったら fpc をインストールします。

$ brew install fpc

PASCAL-P5 のアーカイブを DL して解凍します。

$ cd /tmp
$ curl -OL https://ht-deko.com/software/pascal-p5.tar.gz
$ tar -zxvf pascal-p5.tar.gz
$ cd Pascal-p5/source/

コンパイル

Windows 用バイナリと同じ挙動にするにはソースコードの修正が必要なようです。

note: Homebrew でインストールされた fpc は 3.0.4 [2018/10/2] でした。{$mode ISO} は効くようですが、外部ファイルとの関連付けに assign() が必要な感じです。
image.png

・pcom.pas の修正
任意のエディタで pcom.pas を開いてください。

$ nano pcom.pas

Assign の処理を追加します (Line: 5986 付近)。追加場所は (*initialize*) で検索してください。

pcom.pas
  write('P5 Pascal compiler vs. ', majorver:1, '.', minorver:1);                                      
  if experiment then write('.x');                                                                     
  writeln;                                                                                            
  writeln('Pascal-P5 complies with the requirements of level 0 of ISO/IEC 7185.');                    
  writeln;        

  (*initialize*)                                                                                      
  (************)  
  {$ifdef fpc}        // <- 追加
  assign(prd, 'prd'); // <- 追加
  assign(prr, 'prr'); // <- 追加
  {$endif}            // <- 追加
  initscalars; initsets; inittables;                                                                 

・pint.pas の修正
任意のエディタで pint.pas を開いてください。

$ nano pint.pas

Assign の処理を追加します (Line: 2432 付近)。追加場所は P5 Pascal interpreter で検索してください。

pint.pas
  write('P5 Pascal interpreter vs. ', majorver:1, '.', minorver:1);                                   
  if experiment then write('.x');                                                                     
  writeln;                                                                                            
  writeln;                                                                                                                                                                                                

  {$ifdef fpc}        // <- 追加
  assign(prd, 'prd'); // <- 追加
  assign(prr, 'prr'); // <- 追加
  {$endif}            // <- 追加

  { !!! remove this next statement for self compile }                                                 
  {elide}rewrite(prr);{noelide}       

・コンパイル
pcom.pas と pint.pas を Free Pascal でコンパイルします。{$mode ISO} オプションを付けます。

$ fpc -Miso -v0 -Px86_64 pcom.pas
$ fpc -Miso -v0 -Px86_64 pint.pas

エラーが出るようなら、環境変数 MACOSX_DEPLOYMENT_TARGET にバージョンを明示的に指定してコンパイルします。

$ MACOSX_DEPLOYMENT_TARGET=10.13 fpc -Miso -v0 -Px86_64 pcom.pas
$ MACOSX_DEPLOYMENT_TARGET=10.13 fpc -Miso -v0 -Px86_64 pint.pas

バイナリを ~/p5/ にコピーします 4

$ mkdir ~/p5
$ cp pcom pint ~/p5/

もうソースコードは不要です。

$ cd /tmp
$ rm -Rf Pascal-P5/
$ rm -f pascal-p5.tar.gz

スクリプトファイル

スクリプトファイルを適当な場所 (~\p5) に作成します。

$ cd ~/p5/

スクリプトファイルは Linux と共通です。compile / run / p5 を作成してください。

・パーミッション変更
スクリプトを実行できるようにパーミッションを変更しておきます。

$ chmod 755 compile run p5

PASCAL-P5 の使い方 (macOS)

Linux の場合と同じです。まずは hello.pas を ~/p5/ に作成します。

$ nano hello.pas
hello.pas
program Hello(Output);
begin
  writeln('Hello, world.');
end.
$ ./compile hello
$ ./run hello

または

$ ./p5 hello

でコンパイルして実行します。
image.png
あまり macOS に詳しくないのでスクリプトは適当でないかもしれません。

■ macOS の場合 (gpc でコンパイルする場合)

2021/10 現在、macOS (64bit) で動作する GNU Pascal (gpc) は存在しません。

macOS は 10.15 Catalina 以降、32bit アプリケーションが動作しません。

■ Linux の場合 (FPC でコンパイルする場合)

Linux 環境で Free Pascal (fpc) を用いてソースコードから Pascal-P5 をビルドする手順です。

アーカイブの \pascal-p5.tar\Pascal-p5\gpc\linux_X86 に Ubuntu (x86) 用のバイナリが一応含まれてはいるのですが、32bit バイナリなので WSL とかでは動作しません。

環境設定

Free Pascal をインストールしておきます。

$ sudo apt-get install fpc

PASCAL-P5 のアーカイブを解凍します。

$ cd /tmp
$ curl -OL https://ht-deko.com/software/pascal-p5.tar.gz
$ tar -zxvf pascal-p5.tar.gz
$ cd Pascal-p5/source/

コンパイル

Windows 用バイナリと同じ挙動にするにはソースコードの修正が必要かもしれません。

Note: 検証に使った WSL 用の 3.0.0+dfsg-2 [2016/01/28] では以下の修正が必要でした。少なくともプログラムヘッダに対しては {$mode ISO} が効かない感じです。

Note: WSL をアップデートして 3.0.4+dfsg-18ubuntu2 [2018/08/29] で試してみたら、ソースコードの修正は一切不要でした。プログラムヘッダに対して {$mode ISO} が効くようで、標準 Pascal と同じ解釈になっています。
image.png

Note: Windows 11 の WSL2 上の fpc 3.0.4+dfsg-23 [2019/11/25] で試してみたら、{$mode ISO} は効くようですが、外部ファイルとの関連付けに assign() が必要な感じです。修正点は macOS の場合と同じです (pcom / pint 共に 1. の修正は不要)。
image.png

・pcom.pas の修正
任意のエディタで pcom.pas を開いてください。

$ nano pcom.pas

 1. {elide} の行を削除します (Line: 394)。!!! remove で検索するとみつかります。この修正は fpc のバージョンによっては不要です。

pcom.pas
    { !!! remove this statement for self compile }
    {elide}prd,prr: text;{noelide}       { output code file } // <- この行を削除

 2. Assign の処理を追加します (Line: 5986 付近)。追加場所は (*initialize*) で検索してください。

pcom.pas
  write('P5 Pascal compiler vs. ', majorver:1, '.', minorver:1);                                      
  if experiment then write('.x');                                                                     
  writeln;                                                                                            
  writeln('Pascal-P5 complies with the requirements of level 0 of ISO/IEC 7185.');                    
  writeln;        

  (*initialize*)                                                                                      
  (************)  
  {$ifdef fpc}        // <- 追加
  assign(prd, 'prd'); // <- 追加
  assign(prr, 'prr'); // <- 追加
  {$endif}            // <- 追加
  initscalars; initsets; inittables;                                                                 

・pint.pas の修正
任意のエディタで pint.pas を開いてください。

$ nano pint.pas

 1. {elide} の行を削除します (Line: 317)。!!! remove で検索するとみつかります。この修正は fpc のバージョンによっては不要です。

pint.pas
      { !!! remove this next statement for self compile }                                                 
      {elide}prd,prr     : text;{noelide}(*prd for read only, prr for write only *)  // <- この行を削除

 2. Assign の処理を追加します (Line: 2432 付近)。追加場所は P5 Pascal interpreter で検索してください。

pint.pas
  write('P5 Pascal interpreter vs. ', majorver:1, '.', minorver:1);                                   
  if experiment then write('.x');                                                                     
  writeln;                                                                                            
  writeln;                                                                                                                                                                                                

  {$ifdef fpc}        // <- 追加
  assign(prd, 'prd'); // <- 追加
  assign(prr, 'prr'); // <- 追加
  {$endif}            // <- 追加

  { !!! remove this next statement for self compile }                                                 
  {elide}rewrite(prr);{noelide}       

・コンパイル
pcom.pas と pint.pas を Free Pascal でコンパイルします。{$mode ISO} オプションを付けます。

$ fpc -Miso -v0 pcom.pas
$ fpc -Miso -v0 pint.pas

~/p5/ にバイナリをコピーしておきます 5

$ mkdir ~/p5
$ cp pcom pint ~/p5/

もうソースコードは不要です。

$ cd /tmp
$ rm -Rf Pascal-P5/
$ rm -f pascal-p5.tar.gz

スクリプトファイル

スクリプトファイルを適当な場所 (~\p5) に作成します。Windows 用と同じ使い方ができるスクリプトファイルです。

$ cd ~/p5/

・compile
ソースファイルをコンパイルして P-CODE 形式ファイルを出力するスクリプトファイルです。

compile
#!/bin/bash
#
# Compile file in batch mode using FPC Pascal.
#
# Runs a compile with the input and output coming from/
# going to files.
#
# Execution:
#
# Compile <file>
#
# <file> is the filename without extention.
#
# The files are:
#
# <file>.pas - The Pascal source file
# <file>.p5  - The intermediate file produced
# <file>.err - The errors output from the compiler
#
# Note that the l+ option must be specified to get a full
# listing in the .err file (or just a lack of l-).
#

if [ -z "$1" ]
then
   echo "*** Error: Missing parameter"
   exit 1
fi

if [ ! -f $1.pas ]
then
   echo "*** Error: Missing $1.pas file"
   exit 1
fi

cp $1.pas prd
rm -f $1.p5
./pcom | tee $1.err
rm -f prd

#
# The status of the compile is not returned, so convert a non-zero
# error message to fail status
#
grep -q "Errors in program: 0" $1.err
rc=$?
if [[ $rc != 0 ]] ; then

    rm -f prr
    exit 1

fi
#
# Move the prr file to <file.p5>
#
rm -f $1.p5 $1.err prd
mv prr $1.p5

・run
P-CODE 形式ファイルを解釈して実行するスクリプトファイルです。

run
#!/bin/bash
#
# Run a Pascal file in batch mode using FPC Pascal
#
# Runs a Pascal intermediate in batch mode.
#
# Execution:
#
# run <file>
#
# <file> is the filename without extention.
#
# The files are:
#
# <file>.p5  - The intermediate file
# <file>.inp - The input file to the program
#

if [ -z "$1" ]
then
   echo "*** Error: Missing parameter"
   exit 1
fi

if [ ! -f $1.p5 ]
then
   echo "*** Error: Missing $1.p5 file"
   exit 1
fi

cp $1.p5 prd
if [ -f $1.inp ]
then
  ./pint < $1.inp
else
  ./pint
fi

rm -f prd prr

・p5
ソースコードファイルをコンパイルして実行するスクリプトファイルです。

p5
#!/bin/bash
#
# Compile with P5 using FPC Pascal
#
# Execute with:
#
# p5 <file>
#
# Where <file> is the name of the source file without
# extention. The Pascal file is compiled and run.
# Any compiler errors are output to the screen. Input
# and output to and from the running program are from
# the console, but output to the prr file is placed
# in <file>.out.
# The intermediate code is placed in <file>.p5.
#

if [ -z "$1" ]
then

   echo "*** Error: Missing parameter"
   exit 1

fi

if [ ! -f $1.pas ]
then

   echo "*** Error: Missing $1.pas file"
   exit 1

fi

echo
echo Compiling and running $1
echo
cp $1.pas prd
./pcom | tee $1.err
rm -f prd

grep -q "Errors in program: 0" $1.err
rc=$?
if [[ $rc != 0 ]] ; then

    rm -f prr
    exit 1

fi

rm -f $1.p5 $1.err prd
mv prr $1.p5
cp $1.p5 prd
./pint
rm -f prd prr

・パーミッション変更
スクリプトを実行できるようにパーミッションを変更しておきます。

$ chmod 755 compile run p5

PASCAL-P5 の使い方 (Linux)

hello.pas を ~/p5/ に作成します。

$ nano hello.pas
hello.pas
program Hello(Output);
begin
  writeln('Hello, world.');
end.
$ ./compile hello
$ ./run hello

または

$ ./p5 hello

でコンパイルして実行します。
image.png
あまり Linux に詳しくないのでスクリプトは適当でないかもしれません。

■ Linux の場合 (gpc でコンパイルする場合)

Linux 環境で GNU Pascal (gpc) を用いてソースコードから Pascal-P5 をビルドする手順です。

GNU Pascal の RPM は以下にあります。RPM が使えるディストリビューションなら、パッケージとして gpc が登録されていなくても導入はそれほど難しくありません。

rpm 説明
gpc-20070904*.x86_64.rpm 64bit Linux 用の RPM
gpc-20070904*.i686.rpm 32bit Linux 用の RPM

CentOS 6 (32bit) の VM があったので試してみました。

$cd /tmp
$curl -OL <目的の RPM>
$rpm -ivh gpc*

無事 GNU Pascal を導入できました。
image.png

環境設定

アーカイブを DL して解凍しておきます。

$ cd /tmp
$ curl -OL https://ht-deko.com/software/pascal-p5.tar.gz
$ tar -zxvf pascal-p5.tar.gz
$ cd Pascal-p5/source/

コンパイル

pcom.pas と pint.pas を GNU Pascal でコンパイルします。ソースコードの修正は不要です。

$gpc --classic-pascal-level-0 --no-warnings --transparent-file-names --no-range-checking -o pcom pcom.pas
$gpc --classic-pascal-level-0 --no-warnings --transparent-file-names --no-range-checking -o pint pint.pas

pcompint が生成されていると思うので、これをコピーして使います。スクリプトは fpc の場合と同じです。

Note: Pascal-p5 フォルダで ./setpath .configure make すると Pascal-p5/bin/ フォルダに pcom と pint が生成されます。スクリプトも Pascal-p5/bin/ フォルダにあるものがそのまま使えますが、改行コードが CR+LF なので、nkf などを使って LF に変換しないとエラーになります。

$sudo yum install nkf

$cd /tmp/Pascal-p5/bin/
$nkf -Lu --overwrite compile run p5

また、Pascal-p5/bin/ にあるスクリプトは pcom / pint にパスが通ってる前提なのと、compile と run は結果が画面にエコーされないのと、run は入力ファイルがなくても *.inp ファイルを要求するので注意が必要です。

$export PATH="/tmp/Pascal-p5/bin/:$PATH"
$./compile hello
$cat hello.err
$touch hello.inp
$./run hello
$cat hello.lst

image.png

■ X68000 の場合

今回の趣旨からはちょっと外れますが X68000 (Human68K) だと Pure Pascal が標準 Pascal ですね。
image.png

■ Delphi で Pascal-P5 をビルド

できたので、別記事にまとめました。

■ Pascal IDE (Windows)

Pascal-P5 を簡単に扱えるようにするための IDE を作りました。

image.png
image.png
Linux とかだとシェルスクリプトで作れそうな IDE ですが、こんなものでもあると便利です。

See also:

おわりに

とりあえず、目的は達成されました!めでたしめでたし...。

K&R の K の方へ

K&R の K の方「Why Pascal is Not My Favorite Programming Language (何故 Pascal はお気に入りのプログラミング言語ではないのか)」 なんてのを書いていましたが Turbo Pascal や Delphi...それ以前の Apple の Pascal ですらその問題の多くは解決しています (好みの問題は残りますが)。

先の論文が書かれたのは 1981 年ですが、

  • 1983: Pascal 最初の ISO 規格化 / Turbo Pascal 1.0 / Apple Lisa Clascal
  • 1985: Apple による Object Pascal
  • 1989: Turbo Pascal 5.5 (Object Pascal)
  • 1990: ISO 標準 Pascal 改訂
  • 1991: ISO 拡張 Pascal 規格化
  • 1993: Pascal へのオブジェクト拡張 (ドラフト)
  • 1995: Delphi 1.0 (Object Pascal)

それ以降で (Object) Pascal が進化していないハズもなく。

例えば、論文に書かれていたループの問題についてですが、標準 Pascal だと

loop.pas
program loop(output);
begin
  while True do
    begin
      break;
    end;
end.

このような break を使ったループの脱出はできません。
image.png
Delphi とかだと普通にできます。
image.png

Linux の L の方へ

Linux の L の方の Pascal 嫌いという話についても古い Pascal に基づくものなので的外れな指摘もあるかと思います。

例えば

Of course, in stupid languages like Pascal,
where labels cannot be descriptive, goto's can be bad.

labeltest.pas
program labeltest(output);
label 
  jump;
begin
  goto jump;
  writeln('Hello');
jump:
  writeln('World');
end.

確かに標準 Pascal だとラベルに任意の名前を付ける事はできず、符号なしの 4 桁以下の整数を指定する必要がありますが、
image.png
Delphi ならラベルに識別子が使えます (符号なしの整数も使えます)。
image.png

古い Pascal しか知らないと「Pascal...面倒くさいよね!」という意見が出てしまうのもわからなくはないですが、Delphi 等のモダンな (Object) Pascal が面倒くさい訳ではありません。

そして最新版の Delphi

image.png

魔改造 Pascal である Delphi には無償版 (Community Edition) もあるので、K の方や L の方が言ってた事が今でも正しい指摘なのかどうかをぜひ試してみてください。

... Delphi 使いは逆に標準 Pascal を触ってみて Delphi の有難みを知ってください (w


  1. Pascal-P5 の fpc / gpc フォルダには Linux (Intel x86) 用のバイナリも含まれているのですが 32bit バイナリなので、例えば WSL の Ubuntu 等では実行できません。 

  2. GNU Pascal でコンパイルされているようです。最新版のツリーには最新版でコンパイルされた EXE が含まれていないかもしれません (古いバイナリなら gpc\windows_X86 にあります)。 

  3. バッチファイルは *.dpr も許容するようにしてあります。 

  4. /usr/bin/ へコピーする予定でしたが、最近の macOS はウルサクなったみたいなのでこうしました。 

  5. 当初は /usr/bin/ へコピーするようにしていましたが、Windows や macOS と同じ構成にするために ~/p5/ にバイナリとスクリプトを集めるように変更しました。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7