● StrCalc BASIC の実装
4.ソースコードの読み込みと実行
実際に処理する BASIC ソースコードをメモリ上に読み込み、関数StrCalc_BASIC を実行します。
BASICPARAM構造体のメンバpsource にソースコードが格納されているバッファのアドレス、src_size にはソースコードの文字数を設定します。
例1. 文字列定数を指定した場合
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <time.h>
#include "sc39.h"
int __stdcall usr_print(PSTRCALC_PARAM prm,char *arg,int len,void *param)
{
int ret;
prm->str = arg;
if ((ret = StrCalc(prm)) != STATUS_NORMAL)
return ret;
printf("%.16G\n",prm->ans);
return STATUS_NORMAL;
}
USERSTATEMENT table[] = {
{ "print", 5, usr_print, NULL }
};
void basic_setting(PBASICPARAM pbas)
{
pbas->random_seed = (unsigned)time(NULL);
pbas->stackcnt_if = 16;
pbas->stackcnt_for = 16;
pbas->stackcnt_gosub = 16;
pbas->b_localparam = 1;
pbas->b_ignore_subcnt = 0;
pbas->b_remark_colontype = 0;
pbas->b_remark_ignorestr = 0;
pbas->b_check_dup_label = 1;
pbas->b_naked_us = 0;
pbas->b_us_check = 0;
pbas->b_removespace = 0;
pbas->b_srand = 1;
pbas->fprologue = NULL;
pbas->fevery = NULL;
pbas->fepilogue = NULL;
pbas->proc_exparam = NULL;
pbas->psubst = NULL;
pbas->subst_exparam = NULL;
pbas->pus = table;
pbas->uscnt = sizeof(table) / sizeof(USERSTATEMENT);
}
void main(void)
{
STRCALC_PARAM sc;
BASICPARAM bas;
int ret;
/* StrCalc環境の初期化 */
if (!StrCalc_init(&sc)){
printf("初期化に失敗\n");
return;
}
basic_setting(&bas);
bas.psource = "\
for i = 0 to 10\n\
@print i\n\
next\
";
bas.src_size = strlen(bas.psource); /* ヌル分を含まない事に注意 */
/* StrCalc BASIC の実行 */
ret = StrCalc_BASIC(&sc,&bas);
/* StrCalc環境の終了 */
StrCalc_term(&sc);
if (ret != STATUS_NORMAL)
printf("line : %lu error. %d\n",bas.stop_lineno,ret);
}
例1ソースファイル(zip)
ソースコードを格納するバッファは、BASIC 処理が終了するまで存在しているものであれば、どのような種類のものでもかまいません。
例1 では文字列定数を渡しています。サイズが大きなソースコードを実行する用途には向いていませんが、ちょっとした実験等を行う場合は、このように簡単に済ます事ができます。
例2. テキストファイルを読み込む
(関数usr_print 、basic_setting は例1と同じ)
/* ファイルサイズ分のメモリを確保し、テキストを読み込む */
char *load_src(char *filename,unsigned long *psize)
{
FILE *fp;
char *ptr;
size_t ret,size;
if ((fp = fopen(filename,"rb")) == NULL)
return NULL;
if ((long)(size = _filelength(_fileno(fp))) <= 0 ||
(ptr = (char *)malloc(size + 1)) == NULL)
{
fclose(fp);
return NULL;
}
*psize = size;
ret = fread(ptr,1,size,fp);
fclose(fp);
if (ret < size){
free(ptr); return NULL;
}
ptr[size] = 0;
return ptr;
}
#define FILENAME "testbas.txt"
void main(void)
{
STRCALC_PARAM sc;
BASICPARAM bas;
int ret;
if (!StrCalc_init(&sc)){
printf("初期化に失敗\n");
return;
}
basic_setting(&bas);
if ((bas.psource = load_src(FILENAME,(size_t *)&bas.src_size)) == NULL){
StrCalc_term(&sc);
printf("ファイルの読み込みに失敗\n");
return;
}
ret = StrCalc_BASIC(&sc,&bas);
StrCalc_term(&sc);
free(bas.psource);
if (ret != STATUS_NORMAL)
printf("line : %lu error. %d\n",bas.stop_lineno,ret);
}
この例では、ヒープを確保し、そこにテキストファイルの内容を読み込みます。
次の内容のテキストファイルを指定すると、例1 と同じ結果になります。
for i = 0 to 10
@print i
next
例2ソースファイル(zip)