モジュール化、名前空間について少し説明します。
あくまで私の見解で、絶対正しいとは自信を持って言い切れませんので、間違い等あるかもしれません。
詳しくは、「HSP3モジュール機能ガイド」という文書がHSPのパッケージに同梱されているのでそちらをみてください。
「モジュール化」というのは文字通り「モジュール」にすることですが、そもそもHSPにおけるモジュールとは、
「名前空間」で分割された「部分」のことです。
「名前空間」という言葉が出てきましたね。"空間"と聞くと三次元空間をイメージしがちですが、ここでの空間はそういったものではなく、
概念的なものです。数学で言う「集合」のような存在です。
HSPのプログラムはすべてなんらかの名前空間に属しています。デフォルトでは「hsp」という名前空間に属しています。これをグローバル空間と言うそうです。
ある名前空間「name」に属する定数・変数,命令の正式名称は「@name」がついたものです。
例えばエディタを起動してただ mes "3" と記述すれば、「mes」のフルネームは「mes@hsp」なのです。
(※変数の場合は「hsp」という名前空間には居ないようです。「a」と「a@hsp」は区別されます。ここらへんは私にはよくわかっていません。)
なんでフルネームで呼ばなくてもOKなのかということについてですが、それは、ある空間内のコード中で空間の名前を省略した場合、
コンパイラにより後に自動で補完されるからです。
ですから、最終的にはやはりフルネームで呼ばれています。コンピュータの原則は一意性ですから、あいまいさは許されないわけですね。
ただ、人間は「文脈」が読めますから、分かり切った名前空間名をわざわざ記述するという手間のかかることをしたくない(せずとも正しく読める)わけで、
エディタの中では省略できるように設計されているのです。
(ちょうど、全国チェーン店Xがあるとして、A県にいる人同士の会話でA県のX店を指すときに、特に理由もなくわざわざ「"A県の"X店に行こう」ということはないし、
そんなことをしなくてもちゃんと会話が成り立つのと同じイメージです。)
名前空間は自分で新たに作ることもできます。それを可能にするが「#module」と「#global」というコードです。
この二者に挟まれた部分は別の名前空間に属します。
例えば
a = 1
#module hoge
a = 2
#global
(※このコードは実行しても意味を成しませんが、ここでは話をわかりやすくするためにあえてツッコミはなしで。)
においてグローバル空間に属する「a」とhoge空間に属する「a」は違います。両者には正式名称があり、それぞれ「a@」,「a@hoge」です。
ある空間から別の空間の中の定数・変数や命令を呼び出すには、ちゃんとフルネームで呼んであげる必要があります。
例えば、
#module hoge
#deffunc func_hoge
a = 2
return
#global
func_hoge
mes a@hoge
(#deffuncが出てきましたが、後に説明します。ここでは深く考えず、hoge空間のaに2を代入する作業のためのものだと思ってください。)
というコードで、グローバル空間からhoge空間のaを参照しています。ただ「a」と書くだけではだめです。それだと、a@が参照されてしまいます。
#module〜#globalは放っておいて実行されるものではありません。
#module hoge
a = 2
#global
mes a@hoge
こうすると、2が表示されそうな気がしますが、そうではありません。モジュールは呼び出してやらないと何もしません。空間ですから。動くものを中に入れないと意味がありません。
モジュールはラベルとは違いますので、単純に上から実行されるわけではないのです。もう少し言うと、どの位置においても普通は差し支えないということです。
そこで、#deffuncを使って新規命令(動くもの)を名前空間(すなわちモジュール)中に作り出すわけです。
#deffuncの使い方はここで述べられるほど単純ではないので、HSPのヘルプを参照してもらうことにし、説明は割愛させてもらいます。
ただ、述べておきたいこととして、どうやら、#deffuncはラベル的な構造になっているようです。最後にreturnがあることからも察しがつきます。
というわけで、質問者さんのスクリプト
cls
pos 20,20 :color 0,0,255 :font msgothic,18,1
mes "青文字"
pcfm "赤文字",255
#deffunc pcfm str moj,int c1
pos 20,50 :color c1,0,0 :font msgothic,18,1
mes moj
return
では、#deffuncで作られたラベル的な部分が、pcfmで1回実行され、returnでpcfmの直後に戻ってきます。(サブルーチンみたいですね。このイメージは大事です。)
その後、下へ向かってコードが実行され、2回目に突入します。その時は「呼ばれていない」つまり#deffuncによって成されるはずの作業が行われないままラベルの中身が実行されるので、
mojやc1といったものが何を指すのかが定まらないまま、直後の color で参照されることにより、エラーになってしまうということです。
pcfmの直後にstopを入れたからと言って「空間が2つに分かれる」のではなく、単に2回目の実行を防止しているだけなのです。
先ほど、「モジュールは呼ばないと動かない」と言いましたが、このことを利用すると、質問者さんのスクリプトは次のように改良できます。
cls
pos 20,20 :color 0,0,255 :font msgothic,18,1
mes "青文字"
pcfm "赤文字",255
#module mod_pcfm
#deffunc pcfm str moj,int c1
pos 20,50 :color c1,0,0 :font msgothic,18,1
mes moj
return
#global
1度はpcfmによって呼ばれ、returnでpcfmの直後に戻ってきますが、コードが下へ向かって実行される原則のもとでも、
モジュールmod_pcfmは「呼ばれていない」ので、2度目の実行は起こらないということです。
以上、長々とした説明になってしまいました。お役に立てれば幸いです。