Created
May 23, 2018 12:42
-
-
Save raccy/21738b87051f0ec564d84b4328c2bf89 to your computer and use it in GitHub Desktop.
メモリがなければファイルを使えばいいじゃない
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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