見出し画像

なかなかすごいことになった私のスマホの開発環境

最近の私はほとんどスマホでプログラミングする。通勤時間帯がプログラミング時間というスキマプログラミングである。

Android版のLinuxである「Termux」を利用しているんだが、これが実によくできている。入力したコマンドがなければ『○○をインストールして!』と教えてくれる。インストールすればほぼ悩みなく動作する。

ちょいとプログラミングしてみようと思ったが、自宅でPCを立ち上げてあーだこーだする時間がなかった。スマホでプログラミングは苦肉の策だったんだが、予想以上の環境である。

Linuxは、おそらく最もオープンソースが進んでいるプラットホームではないか。

さて!

今、私のスマホに入っているコンパイラ達である。



C言語

#include <stdio.h>
int main()
{
    printf("Hello World.\n");
    return 0;
}

まずは、C言語。
開発は1972年と古い。
Hello World」だけでも既にいろいろお作法が見えている。

まず、「stdio.h」をインクルードする。「printf」を使うためには必ずインクルードしなければならない。「printf」に限らずライブラリを使用しようと思うといろいろインクルードしなければならない。

そして「main」関数。必ず1つの「main」関数が必要である。また2つ以上あってもいけない。どのプログラムもこの「main」関数からスタートする。

main」関数の型は「int」。これも必ず「int」でなければならない。戻り値は正常終了なら0、異常終了なら0以外を返す。これはシェルスクリプトからこのプログラムを呼び出すときに意味を持つようになる。

さらに関数は {} で括らなければならない。これも絶対に必要。

printf」は標準出力に表示する標準関数である。コードの1文ごとに、これも必ず「;」(セミコロン)が必要である。逆に「;」さえ付ければ一行に複数の文を書くこともできる。

最後は「return」文。関数の型が「void」でなければこれも必ず必要。今回の場合は0(正常修理)固定。実は「printf」にも戻り値があって異常終了という可能性もあるんだが、異常終了する条件もなんとなくはっきりせず、標準出力に表示できないからといって何をどうするねんというのもあって、「printf」文の戻り値はチェックしないことも少なくない。

コンパイル、実行は次の通り。

$ l
hello_c.c
$ cat hello_c.c
#include <stdio.h>                                            int main()
{
        printf("Hello World.\n");                                     return 0;
}
                                                              $ cc hello_c.c -o hello_c
$ l
hello_c*  hello_c.c
$ ./hello_c
Hello World.
$

C++

#include <iostream>
int main()
{
    std::cout << "Hello World." << std::endl;
}

C++である。1983年に登場。
C言語の後継言語で、オブジェクト指向の諸々を機能追加した。後継ではあるのだが、原則として従来のC言語をそのまま使用できることを前提とした。C言語の資源が多く、それが使えないとなるとC++に移行するものが続かないだろうと考えてのことかと思われる。逆に負の遺産も引き継いだとも言える。ヘッダファイルはなくしてほしかった。

標準出力は「cout」を使用する。「printf」も使えるんだが。「printf」は「10進数で表示しろ」とか「文字列として表示しろ」とか、いちいち指示してやらなければならない。「cout」は、表示しようとしているデータの型を把握して、それなりにふさわしいと思われるパターンで適当に表示してくれる。

また、()で引数を指定するのではなく、演算子「<<」をオーバーライトしている。これもC++の成せる技である。

コンパイル、実行は次の通り。

$ l
hello_cpp.cpp
$ cat hello_cpp.cpp
#include <iostream>
int main()
{
        std::cout << "Hello World." << std::endl;
        return 0;
}
$ clang++ hello_cpp.cpp -o hello_cpp
$ l
hello_cpp*  hello_cpp.cpp
$ ./hello_cpp
Hello World.
$

Python

print("Hello World.")

最近流行りのPythonである。1991年に登場したインタプリタ言語である。

うーん。
たった1行になってしまった。

print」関数はPythonの標準関数で、標準関数は何を宣言することもなく使用できる。インタプリタなので関数定義も必ずしも必要ではない(関数も定義したければできる)。1行なので、もはや解説することもない。

実行してみた。

$ l
hello_py.py
$ cat hello_py.py
print("Hello World.")
$ python hello_py.py
Hello World.
$

Java

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World.");
    }
}

1995年に登場したプログラミング言語である。

えーっと。Javaは詳しくないし、面倒くさくもあるのでAIに教えてもらったことをそのまま張り付ける。

このコードは、Javaの基本的な構文を示しています。まず、public class HelloWorldという行で、HelloWorldという名前のクラスを定義しています。クラスとは、Javaのプログラムの基本単位で、データや処理をまとめたものです。次に、public static void main(String[] args)という行で、mainという名前のメソッドを定義しています。メソッドとは、クラスに属する処理の単位で、特定の動作を行うためのコードです。mainメソッドは、Javaのプログラムの実行時に最初に呼び出される特別なメソッドで、プログラムの起点となります。mainメソッドの中には、System.out.println("Hello World");という行があります。これは、標準出力にHello Worldという文字列を出力するためのコードです。System.outは、標準出力を表すオブジェクトで、printlnは、そのオブジェクトが持つメソッドの一つです。printlnメソッドには、引数として出力したい文字列を渡します。引数とは、メソッドに渡すデータのことで、メソッドの動作に影響を与えます。文字列は、ダブルクォーテーションで囲んで表します。
Javaのプログラムを実行するには、コンパイルという作業が必要です。コンパイルとは、人間が書いたコードを、コンピュータが理解できる形式に変換することです。Javaのコンパイルには、javacというコマンドを使います。例えば、上記のコードをHelloWorld.javaというファイルに保存した場合、以下のようにコマンドを実行します。

javac HelloWorld.java

これにより、HelloWorld.classというファイルが生成されます。これが、コンピュータが理解できる形式に変換されたプログラムです。このプログラムを実行するには、javaというコマンドを使います。以下のようにコマンドを実行します。

java HelloWorld

これにより、標準出力にHello Worldという文字列が表示されます。これが、JavaHello Worldを書く方法です。Javaのプログラミングについてもっと学びたい場合は、[こちら]のサイトが参考になるかもしれません。

bing

引用文中にある『[こちら]のサイト』については省略。

少し補足する。
Javaは、C++をさらに発展させた言語である。特徴はいろいろあるだろうが、一番大きいのはプラットホームに依存しないということだろうか。Javaが出てきた当初に抱いた実感である。C++は、プラットホームに依存するWindows対象で作ったオブジェクトはWindowsでしか動かないし、Mac対象で作ったオブジェクトはMacでしか動かないし、Android対象で作ったオブジェクトはAndroidでしか動かない。それだけではない。Intel対象のオブジェクトはIntelでしか動かないし、ARM対象のオブジェクトはARMでしか動かない。CPUOSの両方に依存する。それがプラットホーム依存だ。Javaはその敷居を取り除いた。Java仮想マシンの導入である。それぞれのCPU、そしてOSに対応したJava仮想マシンを用意する。Javaのソースコードは、そのJava仮想マシンの上で動作する。これでプラットホームと直に接することはなくなる。プラットホーム依存からの脱却である。ネットワークという時代の流れがJavaの背中を押した。

その他、Javaという言語仕様にはいろいろ思いが込められているようだが、それらについて言及するにはこの余白はあまりにも小さすぎる。なのでまたそのうちに(多分)。

実行してみる。

$ l
hello_java.java
$ cat hello_java.java
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World.");
    }
}

$ java hello_java.java
Hello World.
$

C#

// C#でHello Worldを出力するプログラム
// Systemネームスペースを使用する
using System;

// Programクラスを定義する
class Program 
{
    // Mainメソッドを定義する
    static void Main(string[] args)
    {
        // ConsoleクラスのWriteLineメソッドを呼び出して、
        // "Hello World!"という文字列を出力する
        Console.WriteLine("Hello World!");
    }
}

C#も使える。驚きである。
C#2000年にMicrosoftが開発した言語である。
生成した実行ファイルはTermux上で直接的には動かない。「mono」から動かす。「mono」はクロスプラットホームの「.NET Framework」だそうだ。C#にとって「.NET Framework」は欠かせない。

さて、コードはというと、Javaにそっくりである。
いちいち列挙するのも面倒なくらいそっくりである。
何の主張も見いだせないくらいそっくりである。
ちなみに、先に出たのはJavaで、C#は後発である(別に何が言いたいというわけでもない)。

クラス名「Program」とは、また実にグローバルなネーミングである。このネーミングを考えたのはAIだが、そのまま許容されるようである。Javaなら悶絶しそうだ(ファイル名とクラスが一致いないとコンパイルエラーになった)。

そしてやはり「Main」がいるのか。右にならえ(過去にならえ)なのか、「Main」を設けるほうが楽なのか(プログラマーが? それともコンパイラが?)。

コンパイル&実行

$ ls
hello_c#.cs
$ cat hello_c#.cs
// C#でHello Worldを出力するプログラム
// Systemネームスペースを使用する
using System;

class Program // Programクラスを定義する
{
    // Mainメソッドを定義する
    static void Main(string[] args)
    {
        // ConsoleクラスのWriteLineメソッドを呼び出し て、
        // "Hello World!"という文字列を出力する
        Console.WriteLine("Hello World!");
    }
}

$ mcs hello_c#.cs
$ ls
hello_c#.cs  hello_c#.exe
$ ./hello_c#.exe
bash: ./hello_c#.exe: cannot execute binary file: Exec format error
$ mono ./hello_c#.exe
Hello World!
$

Swift

print("Hello World!")

だんだんと未経験言語の領域に入ってゆく。
今度はApple言語である。2014年開発。
また1行コードだ。
言うことなし。

実行結果

$ ls
hello_swift.swift
$ cat hello_swift.swift
print("Hello World!")

$ swift hello_swift.swift
Hello World!
$

Golang

package main

import "fmt"

func main() {
    fmt.Println("Hello, world!")
}

次。
Google言語。2009年開発。
似たり寄ったりを見てきてだんだん飽きてきた(笑)。
package」の名称が「main」で、関数も「main」だが、「main」でなくてもいいのか、それとも「main」が必須なのか。
fmt」は何の略称なるぞ?
format」?

実行、コンパイル

$ ls
hello_go.go
$ cat hello_go.go
package main

import "fmt"

func main() {
    fmt.Println("Hello, world!")
}

$ go hello_go.go
go hello_go.go: unknown command
Run 'go help' for usage.
$ go run hello_go.go
Hello, world!
$ go build hello_go.go
$ ls
hello_go  hello_go.go
$ ./hello_go
Hello, world!
$

Kotlin

fun main() {
    println("Hello World!")
}

KotlinAndroid公式のプログラミング言語なのだそうだ。2011年開発。WikipediaによるとJavaよりもKotlinの方が簡単にAndroidアプリを開発できるらしい。それ以上は知らない。

上記はAIが作成したプログラムである。
であるが、コンパイルエラーになった。

error: could not find or load main class hello_kotlin.kt

main」クラスが必要?
面倒だ。コンパイルする方法もAIに教えてもらう。
AIとのやり取りは省略。
-include-runtime」が必要だそうだ。

実行してみる。

$ ls
hello_kotlin.kt
$ cat hello_kotlin.kt
fun main() {
    println("Hello World!")
}

$ kotlinc hello_kotlin.kt -include-runtime -d hello_kotlin.jar
$
$ ls
hello_kotlin.jar  hello_kotlin.kt
$ kotlin hello_kotlin.jar
Hello World!
$

Perl

頑張れAI

こんにちは、これはBingです。PerlHelloWorldを書くのをお手伝いします。😊
Perlは、**プラクティカル・エクストラクション・アンド・レポート・ランゲージ(Practical Extraction and Report Language)**という名前の略です。Perlは、テキスト処理やシステム管理などに優れたスクリプト言語です。Perlは、Larry Wallという人が1987年に開発しました。
PerlHelloWorldを書くには、以下のようなコードを使います。

bing
# PerlでHelloWorldを出力する
print "Hello, World!\n";

このコードは、printという関数を使って、"Hello, World!\n"という文字列を出力します。\nは改行を表します。Perlのコードは、#で始まる行はコメントとして無視されます。
Perlのコードを実行するには、Perlのインタプリタをインストールする必要があります。インタプリタは、コードを読み込んで実行するプログラムです。Perlのインタプリタは、[Perlの公式サイト]からダウンロードできます。
Perlのコードをファイルに保存する場合は、拡張子を.plにするのが一般的です。例えば、hello.plという名前でファイルを作ります。そして、コマンドラインから、以下のように実行します。

bing
perl hello.pl

これで、Hello, World!というメッセージが出力されます。
PerlHelloWorldを書く方法は、以上です。Perlについてもっと知りたい場合は、[Perlのチュートリアル]を参考にしてください。Perlで楽しくプログラミングしてください。😊

bing

AI引用に絵文字が入っているが、これを入れたのもAIである。

$ ls
hello_perl.pl
$ cat hello_perl.pl
# PerlでHelloWorldを出力する
print "Hello, World!\n";

$ perl hello_perl.pl
Hello, World!
$

Ruby

RubyHelloWorldを書くには、以下のコードを使ってみてください。

bing
# RubyでHelloWorldを出力する
puts "Hello, World!"

このコードは、putsというメソッドを使って、ダブルクォーテーションで囲まれた文字列を画面に表示します。putsは、改行を自動的に付けてくれるので、簡単に出力できます。#は、コメントを表す記号で、その行の後ろの部分は実行されません。コメントは、コードの説明やメモなどに便利です。

Rubyは、オブジェクト指向のプログラミング言語で、シンプルで美しく、人間の自然な言語に近い文法を持っています。Rubyは、Webアプリケーションやゲーム、データ分析など、様々な用途に使われています。

Rubyの基本的な文法や機能についてもっと学びたい場合は、[こちら]のチュートリアルを参考にしてください。Rubyの楽しさを体験してみてくださいね。

bing

puts」!
これはまた珍しい。
C言語の標準関数にも「puts」はあるが、「printf」よりも原始的な関数だ。C言語の「puts」関数は書式指定ができない。Rubyの「puts」で出力文字列の書式は指定できるんだろうか。あるいは、書式を指定するには別の関数があるのか。

Ruby1995年にPerlに続く言語として発表された。開発者はまつもとひろゆき。日本発のプログラミング言語である。インタプリタであるがコンパイルも可能。

それにしても、printでもwriteでもなく、なぜpursなんだろう。

$ ls
hello_ruby.rb
$ cat hello_ruby.rb
# RubyでHelloWorldを出力する
puts "Hello, World!"
$ ruby hello_ruby.rb
Hello, World!
$

Scala

なんだコレは。もはや名前も知らない。
おーい、えーあーい。

こんにちは、これはBingです。私はScalahelloworldを書くのを手伝ってみましょう。😊

Scalaは、オブジェクト指向と関数型の両方の特徴を持つマルチパラダイムのプログラミング言語です。Scalaは、Java仮想マシン(JVM)上で動作し、Javaとの相互運用性が高いです。

Scalahelloworldを書くには、以下のコードを使用できます。

// Scalaでhelloworldを書く
object HelloWorld {
  def main(args: Array[String]): Unit = {
    println("Hello, world!")
  }
}

このコードは、HelloWorldという名前のオブジェクトを定義し、mainという名前のメソッドを持ちます。mainメソッドは、プログラムのエントリーポイントとして機能し、コマンドライン引数をargsという名前の配列として受け取ります。Unitは、mainメソッドが何も返さないことを示す型です。printlnは、標準出力に文字列を出力する組み込み関数です。

Scalahelloworldを実行するには、以下の手順に従ってください。

Scalaのコンパイラとランタイムをインストールします。

テキストエディタで上記のコードを書き、HelloWorld.scalaという名前で保存します。

コマンドラインで、scalac HelloWorld.scalaと入力して、ScalaのコードをJavaのバイトコードにコンパイルします。これにより、HelloWorld.classという名前のファイルが生成されます。

コマンドラインで、scala HelloWorldと入力して、Scalaのプログラムを実行します。これにより、Hello, world!というメッセージが表示されます。

以上が、Scalahelloworldを書く方法です。Scalaのプログラミングに興味がある場合は、[こちら]のチュートリアルを参考にしてください。私は、Scalaのプログラミングに関する質問にお答えできます。😊

bing

ん?
関数型?
関数型も書けるの?
じゃあ、関数型を勉強するときはこれで練習する?

$ ls
hello_scala.scala
$ cat hello_scala.scala
// Scalaでhelloworldを書く
object HelloWorld {
  def main(args: Array[String]): Unit = {
    println("Hello, world!")
  }
}

$ scala hello_scala.scala
Hello, world!
$

Fortran

突如として古いコンパイラである。
だが、今でも現役だ。

Fortranhelloworldを書くには、以下のようなコードを使うことができます。

program hello
  print *, "Hello, world!"
end program hello

このコードは、programend programの間にある文を実行するということを意味します。print *は、標準出力に文字列を表示するための命令です。"Hello, world!"は、ダブルクォーテーションで囲まれた文字列リテラルです。

Fortranは、数値計算や科学技術計算に適したプログラミング言語です。1957年に開発されたFortranは、世界で最も古いプログラミング言語の一つです。

bing

そう。かつては「数値計算にはFortran」と言われた時代があった。「事務処理はCobol」、「制御系がC言語」などと言われたものだ(  ̄- ̄)。

あれ?
でも・・・

Fortranって、全大文字じゃなかったっけ?
Fortran77だったかな。

あ、そうか。

Fortran77helloworldを書くには、以下のようなコードを使うことができます。

      PROGRAM HELLO
      WRITE (*,*) 'Hello, world!'
      STOP
      END

このコードは、標準出力にHello, world!という文字列を表示するだけの簡単なプログラムです。Fortran77は、1977年に発表された数値計算に特化したプログラミング言語です。現在では、Fortran90Fortran2003などの新しいバージョンが開発されています。

bing

あ、ほら、やっぱり、全大文字!
っていうか、なんか、随分変わってね?
こんだけ変わったプログラミング言語も珍しいんじゃあないか。

Fortran90のコンパイル、実行
lfortran」で、「a.out」を生成するだけでなく実行もしてる。

$ ls
hello_f90.f90
$ cat hello_f90.f90
program hello
    print *, 'Hello World!'
end program hello

$ lfortran hello_f90.f90
Hello World!
$ ls
a.out  a.out.tmp.o  hello_f90.f90
$ ./a.out
Hello World!
$

Fortran77は、「f2c」とやらで、なんと!C言語に変換するらしい。やってみたかったけど「f2c」が入手できなかった。ちょっと残念。


Cobol

だんだん、何をしているのかわからなくなってきた。記事を書いているのか、AIをコピペしているのか。

まぁ、いいや、たまには。
最後。

Cobolhelloworldを書く方法はいくつかありますが、一般的な方法は以下のようなコードを使うことです。

IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.
PROCEDURE DIVISION.
    DISPLAY "Hello, world!".
    STOP RUN.

このコードは、標準出力にHello, world!という文字列を表示するだけの簡単なプログラムです。Cobolは、1959年に発表されたビジネス用途に特化したプログラミング言語です。現在では、Cobol2002Cobol2014などの新しいバージョンが開発されています。

もし、Cobolの開発環境がない場合は、Dockerを使って簡単に実行できる方法があります。こちらの記事に詳しい手順が書かれています。また、こちらのサイトでは、Micro FocusCobol開発ツールを使ってHello worldプログラムを作成する方法が紹介されています。

Cobolは、古くから使われているプログラミング言語ですが、まだまだ現役で活躍しています。Cobolの魅力や歴史については、こちらのサイトが参考になると思います。Cobolに興味があるなら、ぜひ挑戦してみてください。😊

bing

では、いただきましたコードをコンパイルする。

~/hello/cobol $ l
hello.cobol
~/hello/cobol $ cat hello.cobol
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.
PROCEDURE DIVISION.
    DISPLAY "Hello, world!".
    STOP RUN.
~/hello/cobol $ cobc hello.cobol
hello.cobol:1: error: invalid indicator 'F' at column 7
hello.cobol:2: error: invalid indicator 'M' at column 7
hello.cobol:3: error: invalid indicator 'U' at column 7
hello.cobol:4: error: invalid indicator 'S' at column 7
hello.cobol:5: error: invalid indicator 'O' at column 7
hello.cobol:6: error: PROGRAM-ID header missing
~/hello/cobol $

ん?
んん?

なに?
error?

'F' 'M' 'U' 'S' 'O' ?
全部「column 7」?

どゆこと?

あ、あ、あ。
行番号がいったっけ?

~/hello/cobol $ cat hello.cobol
000010 IDENTIFICATION DIVISION.
000020 PROGRAM-ID. HELLO.
000030 PROCEDURE DIVISION.
000040 DISPLAY "Hello, world!".
000050 STOP RUN.
~/hello/cobol $ cobc hello.cobol
~/hello/cobol $

ふん。
通った。

~/hello/cobol $ l
hello.cobol  hello.so*
~/hello/cobol $ 

出来上がったのは、この「hello.so」なるものか。
では。

~/hello/cobol $ ./hello.so
Segmentation fault
~/hello/cobol $

はい?
せぐめんてーしょんふぉーると?

DISPLAY "Hello, world!".」を実行中しようとしただけなのに、どうやったらそんなことになるのよ。

さあ、出番だよ、AI君。

COBOLhello.cobをコンパイルする方法は、以下のようになります。

まず、hello.cobという名前のファイルを作成し、コンソールに「HELLO WORLD!!」と表示するプログラムを記述します。プログラムの例はこちらにあります。

次に、コンソールで以下のコマンドを入力して、実行形式のファイルを作成します。

cobc -x --free hello.cob

このコマンドでは、-xオプションで実行ファイルを作成し、--freeオプションで自由書式のプログラムを指定しています。

コンパイルが成功すると、helloという名前の実行ファイルが作成されます。

最後に、コンソールで以下のコマンドを入力して、プログラムを実行します。

./hello

すると、コンソールに「HELLO WORLD!!」と表示されます。

以上が、COBOLhello.cobをコンパイルする方法です。詳しくはこちらの記事も参考にしてください。

あい、わかった。
「-x」を付けよう!
知らんけど。

~/hello/cobol $ cobc -x hello.cobol
~/hello/cobol $

コンパイル、OK。

~/hello/cobol $ l
hello*  hello.cobol  hello.so*
~/hello/cobol $

この「hello」というやつか。
いざ、実行。

~/hello/cobol $ ./hello
Hello, world!
~/hello/cobol $

あらまぁ、動いたわ。
-x」って、何なんだ。
-x」があるのとないのと、どう違う?
help

-x build an executable program

cobc -help

それはわかった。
だから、「-x」がない時に出力される「hello.so」てな、何だ?
おい、AI!(だんだん、粗野になってきた)

COBOLが出力する拡張子が.soのファイルは、共有ライブラリファイルと呼ばれるものです。これらのファイルは、COBOLコードを実行するために必要な情報やや機能を含んでいます。例えば、文字列操作や数値計算などの基本的な処理を行うための関数や定数が定義されているかもしれません。また、オペレーティングシステムに依存しないように、、独自のコードに変更を加えることなく、他のプログラムから呼び出すことができます

COBOLコンパイラは、.cobcという拡張子でCOBOLコードをコンパイルします。コンパイルすると、.soという拡張子で実行可能ファイルが生成されます。このファイルは、cobcrunというプログラム名で実行することができます

.soファイルは、LinuxやmacOSなどのUnix系OSやAndroidOSなどのモバイルOSにおいて広く使用されています6。Windowsでは、.dllや.mach-oなどの別の形式に変換する必要があります

.soファイルは、共有ライブラリファイルとしてCOBOLコンパイル器から生成されるものです。これらのファイルは、COBOLコードを実行するために必要な情報やや機能を提供します。

bing

共有ライブラリ!
デフォルトで出力するのがライブラリで、実行ファイルを出力するためにはわざわざ「-x」のオプションがいるということか? ほとんどのコンパイラは逆だと思うんだが。
どうでもいいが「情報やや機能」とは、何だ。
最初は誤字かと思ったが(AIが誤字!)2回もあると、いろいろと勘ぐってしまう。

いずれにしても「so」ファイルも「cobcrun」とやらで実行できるらしい。ここまで来たら試してみるか。

~/hello/cobol $ cobcrun hello.so
libcob: error: module 'hello.so' not found
~/hello/cobol $

は?
not found?
じゃあ、こうか?

~/hello/cobol $ cobcrun ./hello.so
libcob: error: module 'hello.so' not found
~/hello/cobol $

hello.so」が、ない?
???
一筋縄ではいかない。

どうしたら解決できる?
しばらくAIを小突き回してみたんだが、どうにも埒が明かない。
結局、普通に検索して行き着いたのがココ。

いつもお世話になります「stackoverflow」さん。
質問内容が、もう、全く同じで。
同じ人がいるなんて、嬉しいじゃないか。
そんでもって、回答がこちら。

An entry point is a point where you may enter a shared object (this is actually more C then COBOL). GnuCOBOL generates entry points for each PROGRAM-ID, FUNCTION-ID and ENTRY. Therefore your entry point is HELLO-WORLD (which likely gets a conversion as - is no valid identifier in ANSI C - you won't have to think about this when CALLing a program as the conversion will be done internal).

1.Using cobcrun internally does:search for a shared object (in your case HelloWord), as this is found (because you've generated it) it will be loaded

2.search for an entry point in all loaded modules - which isn't found

There are three possible options to get this working:

・As mentioned in Ho1's answer: use cobc -x, the reason that this works is because you don't generate a shared object at all but a C main which is called directly (= the entry point doesn't apply at all)

・preload the shared object and calling the program by its PROGRAM-ID (entry point), either manually with COB_PRE_LOAD=HelloWorld cobcrun HELLO-WORLD or through cobcrun (option available since GnuCOBOL 2.x)

cobcrun -M HelloWorld HELLO-WORLD

・change the PROGRAM-ID to match the source name (either rename or change the source, I'd do the second: PROGRAM-ID. HelloWorld.)

stackoverflow

えーっと、なになに?

GnuCOBOL は、PROGRAM-IDFUNCTION-ID、および ENTRY ごとにエントリ ポイントを生成します。

stackoverflow

面倒じゃ。
対策は3つもあげてくれている。

1つ目。

~/hello/cobol $ cobc -x hello_cob.cob
~/hello/cobol $ l
hello_cob* hello_cob.cob
~/hello/cobol $ ./hello_cob
Hello, world! (on Cobol)
~/hello/cobol $

-x」をつけて「cobc」を実行する。
こうすればライブラリではなく、実行モジュールができる。それはさっきやった。次。

2つ目。
ファイル名と、PROGRAM-IDが異なる場合は、次のように呼び出す。

~/hello/cobol $ cat *cob
000010 IDENTIFICATION DIVISION.
000020 PROGRAM-ID. HELLO.
000030 PROCEDURE DIVISION.
000040 DISPLAY "Hello, world! (on Cobol)".
000050 STOP RUN.
~/hello/cobol $ l
hello_cob.cob hello_cob.so*
~/hello/cobol $ cobcrun -M hello_cob HELLO
Hello, world! (on Cobol)
~/hello/cobol $

この場合、ファイル名が「hello_cob」で、
PROGRAM-ID.が「HELLO」なので、
「cobcrun -M hello_cob HELLO」で呼び出すことになる。
なんと、PROGRAM-ID.にそんな意味があるのか。

3つ目。
ファイル名とPROGRAM-IDを同じにする。

~/hello/cobol $ cp hello_cob.cob HELLO.cob
~/hello/cobol $ cat HELLO.cob
000010 IDENTIFICATION DIVISION.
000020 PROGRAM-ID. HELLO.
000030 PROCEDURE DIVISION.
000040 DISPLAY "Hello, world! (on Cobol)".
000050 STOP RUN. ~/hello/cobol $ cobc HELLO.cob
~/hello/cobol $ ls
HELLO.cob HELLO.so hello_cob.cob hello_cob.so
~/hello/cobol $ cobcrun HELLO
Hello, world! (on Cobol)
~/hello/cobol $

ファイル名を HELLO.so 
PROGRAM-ID.も HELLO

そうすれば、

cobcrun HELLO

だけで実行可能となる。
なるほど。


以上、Termuxでインストール、実行できるコンパイラ達である。まだ他にもあるかもしれない。

私が若い頃はフリーでコンパイラを手にするなどということはできなかった。コンパイラがこれほどザクザクと簡単に入手できるなど、つい嬉しくなってあれもこれもとつつき回してしまう。本格的に使うものはわずかだろうが、いつでも使えるというのは、なんだかウキウキする。

さあ、いつでも、どこでも、プログラミングを勉強できますよ!



この記事が気に入ったらサポートをしてみませんか?