gpbfi
以下のコードを gpbfi.c という名前で保存して
でコンパイル(要ncurses)
gcc -o gpbfi gpbfi.c -lncurses
でコンパイル(要ncurses)
/*
Graghical pbfi 1.0 : Interpreter for the Brainfuck Programming Language
Copyright (C) 2008 Kazuhiko Sakaguchi
Ported to general console (ncurses) by naoya_t
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> // getopt
extern char *optarg;
extern int optind, optopt, opterr;
extern int optreset;
/* #include <windows.h> */
#include <curses.h>
#include <locale.h>
#define DEFAULT_PROGRAM_FILE "program.bf"
#define MEMORY_SIZE 1024
char *program_file = NULL;
char *input_file = NULL;
char *output_file = NULL;
int clock = 50;
int state;
/*
0:実行中
1:通常終了
2:異常終了
*/
#define WHITE 1
#define RED 2
char *program;
int program_;
int program_counter;
unsigned char *memory;
int memory_;
int pointer;
unsigned char *input;
int input_;
int current_input;
unsigned char *output;
int current_output;
/*
初期化
*/
int initialize(int argc, char **argv) // char *program_file )
{
FILE *input_fp;
FILE *program_fp;
int count;
int nest = 0;
/*
コマンドライン引数解析
*/
opterr = 0;
while (getopt(argc, argv, "i:o:c:") != EOF) {
switch (optopt) {
case 'i':
if (optarg != NULL)input_file = optarg;
break;
case 'o':
if (optarg != NULL) output_file = optarg;
break;
case 'c':
if (optarg != NULL) clock = atoi(optarg);
break;
default:
// err.
break;
}
}
argc -= optind;
argv += optind;
if (argc > 0) {
program_file = argv[0];
printf("program file: %s\n", program_file);
} else {
puts("Usage: gpbfi <file>");
exit(0);
}
/*
プログラム読み込み
*/
count = 0;
if (program_file) {
program_fp = fopen(program_file,"r");
}
else {
program_fp = fopen(DEFAULT_PROGRAM_FILE,"r");
}
if (!program_fp) {
fputs("ファイルを読み込めません。",stderr);
exit(1);
}
while (1) {
if (!(count & 15)) {
program = (char *)realloc(program,count + 16);
if (!program) {
fputs("メモリの動的確保に失敗しました。",stderr);
exit(1);
}
}
if (ferror(program_fp)) {
fputs("ファイルを読み込めません。",stderr);
exit(1);
}
switch (program[count] = fgetc(program_fp)) {
case '#':
while (1) {
if (ferror(program_fp)) {
fputs("ファイルを読み込めません。",stderr);
exit(1);
}
if (fgetc(program_fp) == '\r' || fgetc(program_fp) == '\n' || feof(program_fp)) {
break;
}
}
break;
case '+': case '-': case '>': case '<': case ',': case '.':
count++;
break;
case '[':
nest++;
count++;
break;
case ']':
if (!nest) {
fputs("プログラムの構文に誤りがあります。",stderr);
exit(1);
}
nest--;
count++;
break;
}
if (feof(program_fp)) {
if (nest) {
fputs("プログラムの構文に誤りがあります。",stderr);
exit(1);
}
program[count] = '\0';
break;
}
}
fclose(program_fp);
program_counter = program_ = 0;
/*
メモリ初期化
*/
memory = (unsigned char *)calloc(MEMORY_SIZE,sizeof(char));
memory_ = pointer = 0;
/*
入力読み込み
*/
if (input_file) {
input = NULL;
count = 0;
input_fp = fopen(input_file,"r");
if (!input_fp) {
fputs("ファイルを読み込めません。",stderr);
exit(1);
}
while (1) {
if (!(count & 15)) {
input = (unsigned char *)realloc(input,count + 16);
if (!input) {
fputs("メモリの動的確保に失敗しました。",stderr);
exit(1);
}
}
if (ferror(input_fp)) {
fputs("ファイルを読み込めません。",stderr);
exit(1);
}
input[count] = fgetc(input_fp);
if (feof(input_fp)) {
input[count] = '\0';
break;
}
count++;
}
fclose(input_fp);
}
else {
input = (unsigned char *)calloc(16,sizeof(char));
}
input_ = current_input = 0;
/*
出力初期化
*/
output = NULL;
current_output = 0;
return 0;
}
/*
終了処理
*/
int terminate(void)
{
int count = 0;
FILE *output_fp;
if (output_file) {
output_fp = fopen(output_file,"w");
while (1) {
if (current_output == count) break;
fputc(output[count++], output_fp);
}
fclose(output_fp);
}
// free_parsed_arg(parsed_arg);
free(memory);
free(input);
free(output);
free(program);
return 0;
}
int exec_bf(void)
{
int nest;
switch (program[program_counter]) {
case '+':
memory[pointer]++;
program_counter++;
return 0;
case '-':
memory[pointer]--;
program_counter++;
return 0;
case '>':
pointer++;
if (pointer == MEMORY_SIZE) {
state = 2;
return 0;
}
program_counter++;
return 0;
case '<':
pointer--;
if (pointer == -1) {
state = 2;
return 0;
}
program_counter++;
return 0;
case ',':
memory[pointer] = input[current_input];
if (input[current_input]) current_input++;
program_counter++;
return 0;
case '.':
if (!(current_output & 15)) {
output = realloc(output,current_output + 16);
if (!output) return -1;
}
output[current_output] = memory[pointer];
current_output++;
program_counter++;
return 0;
case '[':
if (!memory[pointer]) {
nest = 0;
while (1) {
if (program[program_counter] == '[') {
nest++;
} else if (program[program_counter] == ']') {
if (!--nest) break;
}
program_counter++;
}
}
else {
program_counter++;
}
return 0;
case ']':
if (memory[pointer]) {
nest = 0;
while (1) {
if (program[program_counter] == ']') {
nest++;
}
else if (program[program_counter] == '[') {
if (!--nest) break;
}
program_counter--;
}
}
else {
program_counter++;
}
return 0;
case '\0':
state = 1;
return 0;
default:
return -1;
}
}
void mvhex(int y, int x, int val)
{
mvaddch(y, x, "0123456789ABCDEF"[val >> 4]);
mvaddch(y, x+1, "0123456789ABCDEF"[val & 15]);
}
int draw()
{
int count;
attrset(COLOR_PAIR(WHITE));
// bkgd(COLOR_PAIR(3));
/*
SetBkColor(hdc,0);
Rectangle(hdc,0,0,WIDTH,HEIGHT);
*/
mvprintw(1,1,"プログラム");
if (program_counter < program_) program_ = program_counter;
if (program_counter > program_ + 119) program_ = program_counter - 119;
for (count=0; count<120; count++) {
int val = program[program_ + count];
if (val == 0) break;
if (program_ + count == program_counter) attrset(COLOR_PAIR(RED));
mvaddch(3,2+count,val);
if (program_ + count == program_counter) attrset(COLOR_PAIR(WHITE));
}
mvprintw(5,1,"メモリ");
if (pointer < memory_) memory_ = pointer;
if (pointer > memory_ + 29) memory_ = pointer - 29;
for (count=0; count<40; count++) {
if (memory_ + count == pointer) attrset(COLOR_PAIR(RED));
{
int val = memory[memory_ + count];
mvhex(7,2+count*3,val);
if (val < 0x20) {
/*
mvaddch(9,2+count*3,'^');
mvaddch(9,3+count*3,'@' + val);
*/
mvaddch(9,2+count*3,' ');
mvaddch(9,3+count*3,' ');
} else {
mvaddch(9,2+count*3,' ');
mvaddch(9,3+count*3,val);
}
}
if (memory_ + count == pointer) attrset(COLOR_PAIR(WHITE));
}
mvprintw(11,1,"入力");
count = 0;
for (count=0; count<30; count++) {
int val = input[current_input + count];
if (val == 0) break;
if (count == 0) attrset(COLOR_PAIR(RED));
mvhex(13,2+count*3,val);
mvaddch(15,2+count*3,val);
if (count == 0) attrset(COLOR_PAIR(WHITE));
}
for ( ;count<40; count++) {
if (count == 0) attrset(COLOR_PAIR(RED));
mvaddch(13,2+count*3,'0');
mvaddch(13,3+count*3,'0');
if (count == 0) attrset(COLOR_PAIR(WHITE));
}
attrset(COLOR_PAIR(WHITE));
mvprintw(17,1,"出力");
for (count=0; count<current_output && count<40; count++) {
if (count == current_output-1) attrset(COLOR_PAIR(RED));
{
int val = output[count];
mvhex(19, 2+count*3, val);
mvaddch(21, 2+count*3, val);
}
}
attrset(COLOR_PAIR(WHITE));
mvprintw(23,1,"状態");
switch (state) {
case 0:
mvprintw(25,2,"実行中");
break;
case 1:
mvprintw(25,2,"通常終了");
break;
case 2:
mvprintw(25,2,"異常終了");
break;
}
return 0;
}
int main(int argc, char **argv)
{
setlocale(LC_ALL,"");
initscr();
curs_set(0); // カーソル非表示
noecho();
// keypad(stdscr,TRUE); // カーソルキー有効
start_color();
init_pair(1, COLOR_WHITE, COLOR_BLACK);
init_pair(2, COLOR_RED, COLOR_BLACK);
initialize(argc,argv);
while (state == 0) {
exec_bf();
draw();
usleep(1000 * clock);
refresh();
}
getch(); // hit any key
endwin();
terminate();
return 0;
}
2008年05月25日(日) 01:49:57 Modified by naoya_t