Skip to content

Instantly share code, notes, and snippets.

@raccy
Created May 23, 2018 12:42
Show Gist options
  • Save raccy/21738b87051f0ec564d84b4328c2bf89 to your computer and use it in GitHub Desktop.
Save raccy/21738b87051f0ec564d84b4328c2bf89 to your computer and use it in GitHub Desktop.
メモリがなければファイルを使えばいいじゃない
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdnoreturn.h>
static inline noreturn void die(char *msg)
{
fprintf(stderr, "%s\n", msg);
exit(1);
}
// >
static inline void ptr_incr(FILE *array)
{
if (fseek(array, 1, SEEK_CUR) != 0)
die(u8"ポインタのインクリメントに失敗しました。");
}
// <
static inline void ptr_decr(FILE *array)
{
if (fseek(array, -1, SEEK_CUR) != 0)
die(u8"ポインタのデクリメントに失敗しました。。");
}
static inline int val_get(FILE *array)
{
int c = getc(array);
if (c == EOF) {
if (ferror(array)) die(u8"読み込みに失敗しました。");
clearerr(array);
c = 0;
if (putc(0, array) == EOF) die(u8"書き込みに失敗しました。");
}
ptr_decr(array);
return c;
}
static inline void val_put(int c, FILE *array)
{
if (putc(c, array) == EOF) die(u8"書き込みに失敗しました。");
ptr_decr(array);
}
// +
static inline void val_incr(FILE *array)
{
int c = val_get(array);
c++;
val_put(c, array);
}
// -
static inline void val_decr(FILE *array)
{
int c = val_get(array);
c--;
val_put(c, array);
}
// .
static inline void output(FILE *array)
{
int c = val_get(array);
if (putchar(c) == EOF) die(u8"標準出力の書き込みに失敗しました。");
fflush(stdout);
}
// ,
static inline void input(FILE *array)
{
int c = getchar();
if (c == EOF) die(u8"標準入力の読み込みに失敗しました。");
val_put(c, array);
}
// [
static inline void jump_begin(FILE *array, FILE *script)
{
int c = val_get(array);
if (c != 0) return;
FILE *stack = tmpfile();
if (stack == NULL) die(u8"一時ファイルの作成に失敗しました。");
if (putc(1, stack) == EOF)
die(u8"一時ファイルの書き込みに失敗しました。");
while (true) {
int s = getc(script);
if (s == EOF) {
die(u8"スクリプトの末尾に達しました。");
} else if (s == '[') {
ptr_incr(stack);
} else if (s == ']') {
ptr_decr(stack);
if (val_get(stack) == 1) break;
}
}
fclose(stack);
}
// ]
static inline void jump_end(FILE *array, FILE *script)
{
int c = val_get(array);
if (c == 0) {
return;
}
FILE *stack = tmpfile();
if (stack == NULL) die(u8"一時ファイルの作成に失敗しました。");
if (putc(1, stack) == EOF)
die(u8"一時ファイルの書き込みに失敗しました。");
ptr_decr(script);
ptr_decr(script);
while (true) {
int s = getc(script);
if (s == EOF) {
die(u8"スクリプトの読み込みに失敗しました。");
} else if (s == ']') {
ptr_incr(stack);
} else if (s == '[') {
ptr_decr(stack);
if (val_get(stack) == 1) break;
}
ptr_decr(script);
ptr_decr(script);
}
fclose(stack);
}
int main(int argc, char *argv[])
{
if (argc <= 1) die(u8"スクリプトが指定されていません。");
FILE *script = fopen(argv[1], "r");
if (script == NULL) die(u8"スクリプトファイルが開けません。");
FILE *array = tmpfile();
if (array == NULL) die(u8"一時ファイルの作成に失敗しました。");
int s;
while ((s = getc(script)) != EOF) {
switch (s) {
case '>':
ptr_incr(array);
break;
case '<':
ptr_decr(array);
break;
case '+':
val_incr(array);
break;
case '-':
val_decr(array);
break;
case '.':
output(array);
break;
case ',':
input(array);
break;
case '[':
jump_begin(array, script);
break;
case ']':
jump_end(array, script);
break;
}
}
fclose(array);
fclose(script);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment