From 03941b78edc5e9fba534af06356233f400fd2fc3 Mon Sep 17 00:00:00 2001 From: KAAAsS Date: Thu, 21 Apr 2022 11:50:54 +0800 Subject: [PATCH] =?UTF-8?q?finish=20lab5=20=E8=A1=A5=E5=85=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lab5/user/lab5/apps/init.c | 116 ++++++++++++++++++++++++++++++++++--- 1 file changed, 109 insertions(+), 7 deletions(-) diff --git a/lab5/user/lab5/apps/init.c b/lab5/user/lab5/apps/init.c index acfa870..91459f8 100644 --- a/lab5/user/lab5/apps/init.c +++ b/lab5/user/lab5/apps/init.c @@ -12,6 +12,8 @@ #define SERVER_READY_FLAG(vaddr) (*(int *)(vaddr)) #define SERVER_EXIT_FLAG(vaddr) (*(int *)((u64)vaddr+ 4)) +#define remove_char() {usys_putc('\b'); usys_putc(' '); usys_putc('\b');} + extern ipc_struct_t *tmpfs_ipc_struct; static ipc_struct_t ipc_struct; static int tmpfs_scan_pmo_cap; @@ -21,14 +23,97 @@ static int tmpfs_read_pmo_cap; int fs_server_cap; #define BUFLEN 4096 +#define MAX_FILE_COMPLEMENT_WORD 100 +#define MAX_FILENAME_LEN 255 + +static char *builtin_complement_word[] = {"cd", "ls", "ll", "cat", "echo", "clear"}; +static int n_builtin_complement_word = sizeof(builtin_complement_word) / sizeof(char *); + +static char file_complement_buf[MAX_FILE_COMPLEMENT_WORD * (MAX_FILENAME_LEN + 1)]; + +void path_to_absolute(char *path); +int fs_scan(char *path); + +static int make_file_complement_word(char ***ret_words) { + int n = 0; + static char *words[MAX_FILE_COMPLEMENT_WORD]; + char *buf = file_complement_buf; + char pathbuf[BUFLEN]; + + // 当前目录 + pathbuf[0] = '\0'; + path_to_absolute(pathbuf); + // 列出目录文件 + int ret = fs_scan(pathbuf); + if (ret >= 0) { + char *print_ptr; + struct dirent *dirat; + print_ptr = (char *) TMPFS_SCAN_BUF_VADDR; + + for (int i = 0; i < ret; i++) { + dirat = (struct dirent *) print_ptr; + // 加入结果 + words[n++] = buf; + strcpy(buf, dirat->d_name); + buf += MAX_FILENAME_LEN + 1; + if (n >= MAX_FILE_COMPLEMENT_WORD) { + break; + } + print_ptr += dirat->d_reclen; + } + } + + *ret_words = &words[0]; + return n; +} + +static char *match_complement_words(char **words, size_t n, char *complement, size_t len, int complement_time, int *match_count) { + for (int i = 0; i < n; i++) { + // 前缀匹配 + if (strncmp(complement, words[i], len) != 0) + continue; + // 补全计数检查 + if ((*match_count)++ >= complement_time) { + return words[i]; + } + } + return NULL; +} static int do_complement(char *buf, char *complement, int complement_time) { int r = -1; - // TODO: your code here + int match_count = 0; + size_t len = strlen(complement); + char *matched = NULL; + char **words; + int n_words; + + // 匹配文件 + n_words = make_file_complement_word(&words); + matched = match_complement_words(words, n_words, complement, len, complement_time, &match_count); + + // 匹配 Shell 内建指令 + if (!matched) { + words = builtin_complement_word; + n_words = n_builtin_complement_word; + matched = match_complement_words(words, n_words, complement, len, complement_time, &match_count); + } + + // 匹配结果 + if (matched) { + // 匹配到了 + strcpy(buf, matched); + r = (int) strlen(buf); + } else if (match_count > 0 && complement_time >= match_count) { + // complement_time 大于一次循环 + r = do_complement(buf, complement, complement_time % match_count); + } else { + // 无匹配 + // printf("no match\n"); + } return r; - } extern char getch(); @@ -54,6 +139,10 @@ char *readline(const char *prompt) c = getch(); if (c < 0) return NULL; + if (c != '\t') { + // 重置补全计数 + complement_time = -1; + } if (c == '\r') { // 回车 usys_putc('\n'); @@ -62,9 +151,24 @@ char *readline(const char *prompt) // 退格 if (i > 0) { i--; - usys_putc('\b'); - usys_putc(' '); - usys_putc('\b'); + remove_char(); + } + continue; + } else if (c == '\t') { + // Tab + if (complement_time < 0) { + // 首次补全 + memcpy(complement, buf, i); + complement[i] = '\0'; + } + ret = do_complement(buf, complement, ++complement_time); + if (ret > 0) { + // 替换屏幕内容 + for (j = 0; j < i; j++) + remove_char(); + i = ret; + for (j = 0; j < i; j++) + usys_putc(buf[j]); } continue; } else { @@ -140,12 +244,10 @@ int fs_scan(char *path) fr.count = count; // 发送 - printf("Send ls: %s\n", path); ipc_msg_t *ipc_msg = ipc_create_msg(tmpfs_ipc_struct, sizeof(fr), 1); ipc_set_msg_data(ipc_msg, (void *)&fr, 0, sizeof(fr)); ipc_set_msg_cap(ipc_msg, 0, tmpfs_scan_pmo_cap); ret = ipc_call(tmpfs_ipc_struct, ipc_msg); - printf("Return ls: %d\n", ret); ipc_destroy_msg(ipc_msg); return ret; }