Wiki内検索
最近更新したページ
最新コメント
メニューバー
ここは自由に編集できるエリアです。
タグ
カテゴリー

gpbfi

以下のコードを gpbfi.c という名前で保存して

 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




スマートフォン版で見る

×

この広告は60日間更新がないwikiに表示されております。