-
Notifications
You must be signed in to change notification settings - Fork 0
/
README-bas2c.txt
273 lines (205 loc) · 12.7 KB
/
README-bas2c.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
X-BASIC to C コンバータ bas2c.x
===============================
## 概要
X680x0 の C Compiler PRO-68K (XC) の無償公開版から削除されている X-BASIC to Cコンバータ
(BC.X) を代替するために、自作の Python 版コンバータ bas2c.py を C++ で書き直して X680x0
上で実行できるようにしたものです。
## インストール
bas2c.x と bas2c.def を Human68k のパスの通った同じディレクトリに置いてください。
インストール時にファイル名を BC.X 、BC.DEF と変更しておくことで、オリジナルの BC.X の代わり
として XC から実行することができるようになります。
## 使い方
Human68k のコマンドラインから、
bas2c sample.bas
のように実行すると、X-BASIC のプログラム sample.bas を変換して sample.c を生成します。
生成された C ソースコードは、
cc /w sample.c
と実行することで、XC を用いて実行ファイル sample.x を生成することができます。
(BASICライブラリをリンクするために /W オプションが必要です)
インストール時にファイル名を bc.x に変更した場合は、
cc sample.bas
のように、XC で X-BASIC のプログラムから実行ファイルを直接生成することもできます。
## コマンドラインオプション
bas2c.x は以下のコマンドラインオプションをサポートしています。
オプション指定は -<オプション> /<オプション> のどちらでも可能です。
以下のオプションは BC.X と同様の機能を持ちます。
* -c[TAB数]
変換後の C ソースコードに BASIC の各行をコメントとして出力します。
TAB数 はコメントのインデントに使うタブの数です。デフォルトは 7 です。
* -v
変換中の BASIC ソースコードを標準出力に表示します。
以下は bas2c.x 独自オプションです。
* -u
ソースコード中に X-BASIC の標準関数や外部関数にない関数呼び出しがあった場合、
通常はそれをそのまま出力しますが (BC.X と同じ動作)、このオプションを指定すると
エラーにします。
* -n
通常、変換後の C ソースコードはプログラムの開始時に b_init()、終了時に b_exit()
を呼び出して X-BASIC としての初期化/終了処理を行いますが、このオプションを指定すると
b_init() は呼ばず、b_exit() の代わりに exit() を呼び出します。
* b_init() は X-BASIC プログラムの初期状態に合わせるため以下のような処理を行い、
b_exit() はここで変更した内容を変更前の状態に戻す処理を行っているようです。
* 画面モードの 512×512 への切り替え
* ファンクションキー表示モード設定
* ファンクションキーや特殊キーの定義内容初期化
* CTRL+C 押下時のベクタ設定
* 乱数系列の初期化
* カーソル表示の消去
* -n を指定して出力したソースコードではこれらの処理を行わないため、例えば変換後の
プログラムの終了時に画面が消去されて表示結果が見えなくなるのを防ぐことができる一方で、
初期化が行われていることが前提の処理が正常に動作しなくなる場合があります。
* 具体的には、以下のような現象が発生します。
* キー入力でカーソルキーなどの特殊キーを認識しない (X-BASIC ではこれらのキーに
特別なコントロールコードが割り当てられるため)
* BASIC プログラム中、KEY コマンドでファンクションキーの内容を再定義すると、
Human68k に戻ってもその内容が残ったままになる
* -b
変換時に、式における X-BASIC と C 言語の仕様の違いに対する補正を行いません。
X-BASIC と BC.X の出力とで結果が異なるようなソースコードを変換する場合、通常は
X-BASIC の仕様に合わせるような変換を行いますが、このオプションを指定すると BC.X の
出力に近い結果が得られるようになります。
以下の BC.X のオプションは未サポートです。
* /D (変換の様子を色付きで出力する)
* /E (エラー行を標準出力に表示 -- bas2c.x は常にこの状態です)
* /H (ハッシュバッファ数の指定)
## 関数引数や戻り値での str 型の扱いについて
X-BASIC の str 型(文字列型)変数を関数の引数や戻り値として使う場合、X-BASIC
インタプリタではその変数の値が引数や戻り値として渡される(値渡し)一方、bas2c や
BC.X で変換した C ソースコードではその変数への参照が渡される(参照渡し)という
違いがあります。
この違いは、X-BASIC インタプリタと変換後の C ソースコードでの挙動の違いだけでなく、
アプリケーションのクラッシュを含めた様々な問題を起こす可能性があります。
bas2c.py では、こうした問題の原因となる操作をエラーとして扱います。
`-b` オプションを指定すると、エラーチェックを行わず BC.X と同様の出力を得ることが
できます。
### 関数の str 型引数
str 型変数を引数に取る関数は、BC.X/bas2c の出力ではその変数への参照が引数として
渡されます。このため、関数内で引数変数への代入を行うと、X-BASIC インタプリタでは
呼び出し元の変数には影響を与えない一方で、BC.X の出力では呼び出し元の変数の値も
変わってしまいます。
それだけではなく、X-BASIC インタプリタと BC.X の出力のそれぞれで、以下のような
一見奇妙な挙動を示します。
* X-BASIC インタプリタ
* 関数の str 型引数への代入を行うと、その関数が呼び出されたときに渡された引数の
文字数+1 文字までが格納できるようです。
* BC.X の出力
* 関数の str 型引数への代入を行うと、最大3文字までしか格納できません。更に、
参照渡しのため関数呼び出し元の変数の値も変化します。
-----------------------------------------------------------------------------------
10 str s="abcdef"
20 sfunc(s)
30 print "s=";s
40 end
100 func str sfunc(a;str)
110 a="1234567890"
120 print "a=";a
130 endfunc
X-BASIC インタプリタでの実行結果:
a=1234567
s=abcdef
BC.X 出力の実行結果:
a=123
s=123
-----------------------------------------------------------------------------------
bas2c では、関数の str 型引数への代入をエラーとして扱います。
### 関数の str 型戻り値
str 型の値を返す関数は、BC.X/bas2c の出力では戻り値を格納した変数への参照を返します。
関数内で定義されるローカル変数は関数から戻ると解放されてしまうため、このような変数への
参照を返すと、関数から戻った後に存在しない変数への参照となるため、アプリケーションが
クラッシュする可能性があります。
-----------------------------------------------------------------------------------
10 print sfunc()
20 end
100 func str sfunc()
110 str s="abcdef"
120 return(s) /* return後に変数 s は解放されるため正しくない操作 */
130 endfunc
-----------------------------------------------------------------------------------
bas2c では、str 型を返す関数でローカル変数を返すとエラーとして扱います。
## インライン C 言語機能
BC.X には、X-BASIC プログラム中の `#c` から `#endc` で囲まれた行をそのまま C ソース
コードとして出力する、という未公開機能があります。bas2c.x でも同等の機能をサポート
しています。
X-BASIC では実現できない処理を C のコードとして記述するのに利用できますが、この機能で
出力されるコードは main 関数または func 命令で定義中の関数の中になるため、グローバル変数の
定義や #include ディレクティブなど、関数定義の外でないと書けない処理には使用できないことに
注意が必要です。
### 例:
X-BASIC プログラム (テキスト VRAM の プレーン0 への書き込み):
-----------------------------------------------------------------------------------
10 #c
20 {
30 void B_SUPER(int); /* #includeが使えないので個別にプロトタイプ宣言が必要 */
40 B_SUPER(0); /* スーパーバイザモードへ */
50 }
60 #endc
70 for i=&HE00000 to &HE0FFFF
80 poke(i,&HFF)
90 next
100 end
1000 func poke(a,v) /* アドレスaに値vを書き込む関数 */
1010 #c
1020 *(char *)a = v;
1030 #endc
1040 endfunc
-----------------------------------------------------------------------------------
変換後の C ソースコード
-----------------------------------------------------------------------------------
/******** program start ********/
void main(int b_argc, char *b_argv[])
{
b_init();
{ // #c - #endc の中がそのまま出力される
void B_SUPER(int); //
B_SUPER(0); //
} //
for (i = 0xE00000; i <= 0xE0FFFF; i++) {
poke(i, 0xFF);
}
b_exit(0);
}
/***************************/
int poke(int a, int v)
{
*(char *)a = v; // #c - #endc の中がそのまま出力される
}
-----------------------------------------------------------------------------------
※ インライン C 言語で DOS コールや IOCS コールを使用した場合は、XC でのコンパイルの際に
/Y オプション (DOS/IOCSライブラリの使用) を指定してください。
## bas2c.def について
bas2c.py は、X-BASIC の標準関数や外部関数を C 言語での関数名を変換するために、
bas2c.def というファイルを使用します。
BC.X で使われていた *.DEF ファイル (BASIC.DEF, GRAPH.DEF,...) を 1 ファイルにまとめた
形になっています。
ファイルは以下のようなフォーマットで記述されています。
-----------------------------------------------------------------------------------
[<グループ名>]
<BASIC関数の戻り値型> <BASIC関数名>(<BASIC関数引数型...>) : <C関数名>(<C関数引数型...>)
:
-----------------------------------------------------------------------------------
<グループ名> は、関数呼び出しが使われた際に必要なヘッダファイルを include するために
使われます。例えば、[GRAPH] グループにある関数 (fill(), line()など) がプログラム中で
使われると、変換後の C ソースコードの冒頭に
#include <graph.h>
が追加されます。
適切な C 関数用ヘッダファイルを用意して bas2c.def に関数定義を追加することで、ユーザーが
独自の外部関数を追加することもできます。
※ bas2.def の冒頭には最初のグループとして、特殊な変換規則を必要とする関数、
ステートメントが定義されています。これらの変換規則は bas2c.py 内の変換ルーチンの記述と
連携しているので変更しないようにしてください。
## 制約と注意事項
* オリジナルの BC.X に比べるとプログラムサイズが大きく、実行速度が遅くなっています。
* BC.X は XC ver.1 の頃から使われていることもあり、出力される C ソースコードの関数定義が
(いわゆる)K&R スタイルで書かれていました。bas2c.x は XC ver.2 での利用を前提として
関数定義を ANSI スタイルで出力します。その他、配列の初期化などでも BC.X と異なるコードを
出力します。
* X-BASIC と C 言語とでは演算子の優先順位や論理演算の値が異なります(例えば、真を表す値は
X-BASIC では -1 ですが C 言語では 1 です)。
BC.X はこの違いを考慮せずそのまま C 言語に変換していたため、式の計算結果が X-BASIC と
異なることがありました。bas2c.x では、変換時に必要に応じてカッコを補うことなどにより
計算結果が変わらないようにしています。この挙動は -b オプションによって変更できます。
## ライセンス
bas2c.x は MIT ライセンスとします。
----
URL: https://github.com/yunkya2/bas2c-x68k
Yuichi Nakamura (GitHub: @yunkya2)