|
@@ -2,32 +2,140 @@
|
|
|
#include <stdlib.h>
|
|
|
#include <getopt.h>
|
|
|
#include <string.h>
|
|
|
+#include <stdbool.h>
|
|
|
|
|
|
#include "brainfuck.h"
|
|
|
#define COMMAND_LINE_STR_SIZE (20)
|
|
|
|
|
|
+static bf_env *global_env;
|
|
|
static struct option long_options[] = {
|
|
|
{"version", no_argument, 0, 'v'},
|
|
|
{"help", no_argument, 0, 'h'},
|
|
|
{"eval", required_argument, 0, 'e'},
|
|
|
{0, 0, 0, 0}
|
|
|
};
|
|
|
+char *program_name;
|
|
|
|
|
|
-void printUsage(char *name) {
|
|
|
- printf("Usage: %s[options] file..\n", name);
|
|
|
+void printUsage(void);
|
|
|
+void printVersion(void);
|
|
|
+void printMenu(void);
|
|
|
+int stepModeFunc(bf_env *env);
|
|
|
+int runFile(int argc, char **argv, bf_env *env);
|
|
|
+int runCommandLine_(bf_env *env);
|
|
|
+int runCommandLine(bf_env *env);
|
|
|
+void free_env_at_exit(void);
|
|
|
+int clInformation(int ch, bf_env *env);
|
|
|
+
|
|
|
+int main(int argc, char **argv){
|
|
|
+ int option_index = 0;
|
|
|
+ int status;
|
|
|
+ program_name = *argv;
|
|
|
+ global_env = bf_setEnv();
|
|
|
+ atexit(free_env_at_exit);
|
|
|
+ bf_setEnvStepFunc(global_env, stepModeFunc);
|
|
|
+
|
|
|
+ while (1) {
|
|
|
+ option_index = 0;
|
|
|
+ int c = getopt_long (argc, argv, "vhe:", long_options, &option_index);
|
|
|
+ if (c == -1)
|
|
|
+ break;
|
|
|
+
|
|
|
+ switch (c) {
|
|
|
+ case 0:
|
|
|
+ break;
|
|
|
+ case 'h':
|
|
|
+ printUsage();
|
|
|
+ goto end;
|
|
|
+ case 'v':
|
|
|
+ printVersion();
|
|
|
+ goto end;
|
|
|
+ case 'e': {
|
|
|
+ bf_code code;
|
|
|
+ code = bf_parserBrainFuck_Str((char *) optarg);
|
|
|
+ bf_runBrainFuck(code, global_env);
|
|
|
+ bf_printError("eval error", global_env);
|
|
|
+ bf_freeBrainFuck(code);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ case '?':
|
|
|
+ printUsage();
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ status = runFile(argc, argv, global_env);
|
|
|
+ if (status != 0)
|
|
|
+ return status;
|
|
|
+
|
|
|
+ status = runCommandLine(global_env);
|
|
|
+ if (status == 1) {
|
|
|
+ printf("stdin error\n");
|
|
|
+ return status;
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("BrainFuckPro: bye~\n");
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ end: // 从-v和-h中退出
|
|
|
+ if (argc > 2) {
|
|
|
+ printf("Too many argument\n");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void printUsage(void) {
|
|
|
+ printf("Usage: %s[options] file..\n", program_name);
|
|
|
printf("Options: \n");
|
|
|
printf(" -e --eval\t\tRun code in a string\n");
|
|
|
printf(" -v --version\t\tshow version\n");
|
|
|
printf(" -h --help\t\tshow help\n\n");
|
|
|
|
|
|
- printf("\nFor more information, please see: \n");
|
|
|
- printf("github.com/SuperH-0630/BranchFuckPro\n");
|
|
|
+ printf("CommandLine Options: \n");
|
|
|
+ printf(" v show version\n");
|
|
|
+ printf(" h show help\n");
|
|
|
+ printf(" q quit\n");
|
|
|
+ printf(" m show CommandLine Menu\n");
|
|
|
+ printf("CommandLine Menu: \n");
|
|
|
+ printMenu();
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+ printf("Step Options: \n");
|
|
|
+ printf(" n continue\n");
|
|
|
+ printf(" m show step menu\n");
|
|
|
+ printf("Step Menu: \n");
|
|
|
+ printMenu();
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+ printf(" For more information, please see: \n");
|
|
|
+ printf(" github.com/SuperH-0630/BrainFuckPro\n");
|
|
|
}
|
|
|
|
|
|
-void printVersion() {
|
|
|
+
|
|
|
+void printVersion(void) {
|
|
|
printf("%s", bf_getVersionInfo());
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+void printMenu(void) {
|
|
|
+ printf("+---+----------------------------+\n");
|
|
|
+ printf("+ v + show version +\n");
|
|
|
+ printf("+ h + show help +\n");
|
|
|
+ printf("+ m + show menu +\n");
|
|
|
+ printf("+ w + print env information +\n");
|
|
|
+ printf("+ p + print paper tape +\n");
|
|
|
+ printf("+ r + print read head +\n");
|
|
|
+ printf("+ s + run in step model +\n");
|
|
|
+ printf("+ i + run with information +\n");
|
|
|
+ printf("+ c + clear screen(May not work) +\n");
|
|
|
+ printf("+ q + quit +\n");
|
|
|
+ printf("+ e + exit the menu +\n");
|
|
|
+ printf("+---+----------------------------+\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
int runFile(int argc, char **argv, bf_env *env) {
|
|
|
while (optind < argc) {
|
|
|
FILE *file = fopen(argv[optind], "r");
|
|
@@ -50,95 +158,125 @@ int runFile(int argc, char **argv, bf_env *env) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int runCommandLine_(bf_env *env) {
|
|
|
- int size = COMMAND_LINE_STR_SIZE;
|
|
|
- int status;
|
|
|
- char *str = calloc(size + 1, sizeof(char ));
|
|
|
- fgets(str, COMMAND_LINE_STR_SIZE + 1, stdin);
|
|
|
- while (!strchr(str, '\n') && !feof(stdin) && !ferror(stdin)) {
|
|
|
- char *new = calloc(size + COMMAND_LINE_STR_SIZE + 1, sizeof(char ));
|
|
|
- strcpy(new, str);
|
|
|
- fgets(new + size, COMMAND_LINE_STR_SIZE + 1, stdin);
|
|
|
- free(str);
|
|
|
- str = new;
|
|
|
- size += COMMAND_LINE_STR_SIZE;
|
|
|
+
|
|
|
+int stepModeFunc(bf_env *env) {
|
|
|
+ return clInformation('m', env);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+int clInformation(int ch, bf_env *env) {
|
|
|
+ int return_ = 0;
|
|
|
+ switch (ch) {
|
|
|
+ case 'v':
|
|
|
+ printVersion();
|
|
|
+ break;
|
|
|
+ case 'h':
|
|
|
+ printUsage();
|
|
|
+ break;
|
|
|
+ case 'm':
|
|
|
+ printMenu();
|
|
|
+ printf("Enter the operation:");
|
|
|
+
|
|
|
+ int del_ch;
|
|
|
+ while ((del_ch = getc(stdin) != '\n') && del_ch != EOF)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ ch = getc(stdin);
|
|
|
+ return_ = clInformation(ch, env);
|
|
|
+ goto NOT_CLEAR; // 不用清除stdin
|
|
|
+ case 'q': // 退出菜单
|
|
|
+ break;
|
|
|
+ case 'w':
|
|
|
+ bf_printEnvWithMode(env);
|
|
|
+ break;
|
|
|
+ case 'p':
|
|
|
+ bf_printPaperTape(env);
|
|
|
+ printf("\n");
|
|
|
+ break;
|
|
|
+ case 'r':
|
|
|
+ bf_printHead(env);
|
|
|
+ printf("\n");
|
|
|
+ break;
|
|
|
+ case 's':
|
|
|
+ if (bf_setEnvMode(env, step, -1))
|
|
|
+ printf("step mode on\n");
|
|
|
+ else
|
|
|
+ printf("step mode off\n");
|
|
|
+ break;
|
|
|
+ case 'i':
|
|
|
+ if (bf_setEnvMode(env, information, -1))
|
|
|
+ printf("information mode on\n");
|
|
|
+ else
|
|
|
+ printf("information mode off\n");
|
|
|
+ break;
|
|
|
+ case 'c':
|
|
|
+ system("clear"); // 清空
|
|
|
+ break;
|
|
|
+ case 'e': // 退出菜单
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ printf("Unsupported menu option\n");
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
- bf_code code;
|
|
|
- code = bf_parserBrainFuck_Str(str);
|
|
|
- status = bf_runBrainFuck(code, env);
|
|
|
- bf_printError("command line error", env);
|
|
|
- bf_freeBrainFuck(code);
|
|
|
- free(str);
|
|
|
- return status;
|
|
|
+ int del_ch;
|
|
|
+ while ((del_ch = getc(stdin) != '\n') && del_ch != EOF)
|
|
|
+ continue;
|
|
|
+
|
|
|
+NOT_CLEAR:
|
|
|
+ return return_;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
int runCommandLine(bf_env *env) {
|
|
|
int ch;
|
|
|
- unsigned int count = 0;
|
|
|
|
|
|
- printf("BranchFuck %s (" __DATE__ ", " __TIME__ ")\n", bf_getVersion());
|
|
|
- printf("Welcome to ues BranchFuck CommandLine (Type 'q' to quit)\n");
|
|
|
+ printf("BrainFuck %s (" __DATE__ ", " __TIME__ ")\n", bf_getVersion());
|
|
|
+ printf("Welcome to ues BrainFuck CommandLine (Type 'q' to quit)\n");
|
|
|
+ printf("Type v(version), h(help) and m(menu) for more information\n");
|
|
|
|
|
|
- while (1) {
|
|
|
+ for (unsigned count = 0; true;count++) {
|
|
|
if (feof(stdin) || ferror(stdin))
|
|
|
return 1;
|
|
|
printf("[%d] >", count);
|
|
|
ch = getc(stdin);
|
|
|
if (ch == 'q')
|
|
|
return 0;
|
|
|
- else
|
|
|
+ else if (ch == 'v' || ch == 'h' || ch == 'm') {
|
|
|
+ if(clInformation(ch, env) == 1)
|
|
|
+ return 0; // quit
|
|
|
+ continue;
|
|
|
+ } else
|
|
|
ungetc(ch, stdin);
|
|
|
runCommandLine_(env);
|
|
|
- count++;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-int main(int argc, char **argv){
|
|
|
- int option_index = 0;
|
|
|
- int status;
|
|
|
- bf_env *env = bf_setEnv();
|
|
|
-
|
|
|
- while (1) {
|
|
|
- option_index = 0;
|
|
|
- int c = getopt_long (argc, argv, "vhe:", long_options, &option_index);
|
|
|
- if (c == -1)
|
|
|
- break;
|
|
|
|
|
|
- switch (c) {
|
|
|
- case 0:
|
|
|
- break;
|
|
|
- case 'h':
|
|
|
- printUsage(argv[0]);
|
|
|
- return 0;
|
|
|
- case 'v':
|
|
|
- printVersion();
|
|
|
- return 0;
|
|
|
- case 'e': {
|
|
|
- bf_code code;
|
|
|
- code = bf_parserBrainFuck_Str((char *) optarg);
|
|
|
- bf_runBrainFuck(code, env);
|
|
|
- bf_printError("eval error", env);
|
|
|
- bf_freeBrainFuck(code);
|
|
|
- break;
|
|
|
- }
|
|
|
- default:
|
|
|
- case '?':
|
|
|
- printUsage(argv[0]);
|
|
|
- return 1;
|
|
|
- }
|
|
|
+int runCommandLine_(bf_env *env) {
|
|
|
+ int size = COMMAND_LINE_STR_SIZE;
|
|
|
+ int status;
|
|
|
+ char *str = calloc(size + 1, sizeof(char ));
|
|
|
+ fgets(str, COMMAND_LINE_STR_SIZE + 1, stdin);
|
|
|
+ while (!strchr(str, '\n') && !feof(stdin) && !ferror(stdin)) {
|
|
|
+ char *new = calloc(size + COMMAND_LINE_STR_SIZE + 1, sizeof(char ));
|
|
|
+ strcpy(new, str);
|
|
|
+ fgets(new + size, COMMAND_LINE_STR_SIZE + 1, stdin);
|
|
|
+ free(str);
|
|
|
+ str = new;
|
|
|
+ size += COMMAND_LINE_STR_SIZE;
|
|
|
}
|
|
|
|
|
|
- status = runFile(argc, argv, env);
|
|
|
- if (status != 0)
|
|
|
- return status;
|
|
|
+ bf_code code;
|
|
|
+ code = bf_parserBrainFuck_Str(str);
|
|
|
+ status = bf_runBrainFuck(code, env);
|
|
|
+ bf_printError("command line error", env);
|
|
|
+ bf_freeBrainFuck(code);
|
|
|
+ free(str);
|
|
|
+ return status;
|
|
|
+}
|
|
|
|
|
|
- status = runCommandLine(env);
|
|
|
- if (status == 1) {
|
|
|
- printf("stdin error\n");
|
|
|
- return status;
|
|
|
- }
|
|
|
|
|
|
- printf("BranchFuckPro: bye~\n");
|
|
|
- return 0;
|
|
|
+void free_env_at_exit(void) {
|
|
|
+ bf_freeEnv(global_env);
|
|
|
}
|