30天自制操作系统吧 关注:1,381贴子:4,751
  • 12回复贴,共1

在命令行中,通过上下方向键移动来唤出历史命令实现。

只看楼主收藏回复

来到了23天,似乎就卡住了。最近作息严重混乱。但是自从在命令行上输出dir ,mem的时候就一直想做的命令历史唤出。以前都是想法,现在还是一个想法。不过今天我不打算在让这件事情拖下去。特此公告,众吧友监督,我要尽快实现该功能,造福吧友


IP属地:四川1楼2015-11-26 16:51回复
    二楼放说明,三楼放测试版本源码。测试版本在gcc下面编译通过。欢迎改良与指出BUG,最近耗费脑细胞较多,暂时不去想改良及BUG事情。编译后运行该测试程序:输入纯字母就会被记录进命令缓冲区。输入字符0后代表命令输入完成。然后可以接着输入命令。命令以字符0为结束标志。我由于加入了调试信息所以多了很多打印语句,可以适当去掉。
    #define CMDHIS_NR 4 /* 默认历史命令记录个数 + 1 */
    #define CMDBUF 25 /* 默认历史命令缓冲区大小字节数,包含用于记录命令指针的区域 */
    注意,上面定义的 历史命令数是4,但是实际上最多能存放3个。因为有一个指针需要用来做中转。所以需要减去一个。上面定义的缓冲区是指针加实际字符命令一起的缓存空间。所以上面的命令字符最多容纳8个字符的命令。不好意思,这个是我为了压力测试。及测试BUG特意定义的极限测试。实际上以4的整数倍为最佳。比如第一个为32,第二个为1024等。方便计算,毕竟左右位移等


    IP属地:四川2楼2015-11-29 14:32
    回复
      #include <stdio.h>
      #include <string.h>
      #define CMDHIS_NR 4
      #define CMDBUF 25
      char cmd_buf[CMDBUF];
      struct cmdhistory {
      int first, last, head, tail, now;
      char ** argv;
      char *buf;
      };
      void main(int argc, char **argv)
      {
      char in;
      int i = 0;
      char buf2[30];
      struct cmdhistory cmdhis;
      cmdhis.buf = cmd_buf;
      cmdhis.argv = (char **)cmd_buf;
      *cmdhis.argv = cmdhis.buf;
      cmdhis.first = 0;
      cmdhis.last = 0;
      cmdhis.head = CMDHIS_NR * 4;
      cmdhis.tail = 0; /* not use but we reserving it */
      cmdhis.now = 0;
      printf("\nplease input alphabets less than 30 end by 0\n");
      while(1) {
      in = getchar();
      fflush(stdin);
      //putchar(in[0]);
      //printf("\nin1=%d\n", in[0]);
      /* 以下为console键盘处理部分 */
      if (in >='a' && in <= 'z' || in >= 'A' && in <= 'Z') {
      buf2[i++] = in;
      } else if(in == '0') {
      printf("\nin=%d\n", in);
      buf2[i] = 0;
      i = 0;
      printf("\n-->%s\n", buf2);
      if (cmdhis.head+strlen(buf2)+1 >= CMDBUF) {
      cmdhis.head = CMDHIS_NR << 2;
      }
      printf("\n head:%d\tlenth:%d\tcmdbuf:%d\n", cmdhis.head,
      strlen(buf2), CMDBUF);
      printf("\n buf+head= %p\targv+last= %p\n",
      cmdhis.buf+cmdhis.head, *(cmdhis.argv+cmdhis.last));
      if ((unsigned int)(cmdhis.buf + cmdhis.head) <=
      (unsigned int)*(cmdhis.argv + cmdhis.last) &&
      cmdhis.first != cmdhis.last) {
      while ((unsigned int)(cmdhis.buf + cmdhis.head) +
      strlen(buf2) + 1 >
      (unsigned int)*(cmdhis.argv + cmdhis.last)) {
      printf("before change last:%d\n",cmdhis.last);
      //cmdhis.last++;
      if (++cmdhis.last == CMDHIS_NR) cmdhis.last = 0;
      printf("after change last:%d\n",cmdhis.last);
      if (cmdhis.last == cmdhis.first) break;
      }
      }
      strcpy(cmdhis.buf + cmdhis.head, buf2);
      *(cmdhis.argv + cmdhis.first) = cmdhis.buf + cmdhis.head;
      //cmdhis.head = cmdhis.head + strlen(buf2) + 1;
      //cmdhis.now = cmdhis.first;
      printf("befor op,first is :%d\tlast is:%d\tnow is:%d\n",
      cmdhis.first,cmdhis.last,cmdhis.now);
      printf("argv is :%p\n", *(cmdhis.argv + cmdhis.first));
      printf("buf+ head is :%p\n", cmdhis.buf + cmdhis.head);
      cmdhis.head = cmdhis.head + strlen(buf2) + 1;
      cmdhis.now = cmdhis.first;
      printf("head is :%d\n", cmdhis.head);
      if(++cmdhis.first == CMDHIS_NR) cmdhis.first = 0;
      if(cmdhis.last == cmdhis.first) {
      if(++cmdhis.last == CMDHIS_NR) cmdhis.last = 0;
      }
      *(cmdhis.argv + cmdhis.first) = 0;
      printf("after op,first is :%d\tlast is:%d\tnow is:%d\n",
      cmdhis.first,cmdhis.last,cmdhis.now);
      //cmdhis.now = cmdhis.first;
      //printf("\n<-->%s\n", *(cmdhis.argv+cmdhis.first-1));
      }else if (in == '8' && (*(cmdhis.argv+cmdhis.now) != 0)){
      printf("befor op,first is :%d\tlast is:%d\tnow is:%d\n",
      cmdhis.first,cmdhis.last,cmdhis.now);
      cmdhis.now++;
      if(cmdhis.now == cmdhis.first)
      cmdhis.now--;
      if(cmdhis.now == CMDHIS_NR){
      if(cmdhis.first == 0) {
      cmdhis.now--;
      }else {
      cmdhis.now = 0;
      }
      }
      if(*(cmdhis.argv+cmdhis.now) != 0) {
      //cons_putstr0(struct CONSOLE *cons, char *s);
      printf("\ncmdhistory-down-->%s\n", *(cmdhis.argv + cmdhis.now));
      }
      printf("after op,first is :%d\tlast is:%d\tnow is:%d\n",
      cmdhis.first,cmdhis.last,cmdhis.now);
      }else if (in == '2' && (*(cmdhis.argv+cmdhis.now) != 0)){
      printf("befor op,first is :%d\tlast is:%d\tnow is:%d\n",
      cmdhis.first,cmdhis.last,cmdhis.now);
      cmdhis.now--;
      if(cmdhis.first < cmdhis.last && cmdhis.now < 0)
      cmdhis.now = CMDHIS_NR-1;
      if(cmdhis.now < cmdhis.last)
      cmdhis.now = cmdhis.last;
      if(*(cmdhis.argv+cmdhis.now) != 0) {
      //cons_putstr0(struct CONSOLE *cons, char *s);
      printf("\ncmdhistory-up-->%s\n",
      *(cmdhis.argv + cmdhis.now));
      }
      printf("after op,first is :%d\tlast is:%d\tnow is:%d\n",
      cmdhis.first,cmdhis.last,cmdhis.now);
      }else {
      }
      }
      }


      IP属地:四川3楼2015-11-29 14:35
      收起回复
        /* 已经在halibote中测试通过,系统修改过程如下 */
        /* 第一步,在bootpack.h中在console.c段添加如下头文件内容 */
        #define CMDHIS_NR 32
        #define CMDBUF 1024
        struct CMDHISTORY {
        int first, last, head, tail, now;
        char ** argv;
        char *buf;
        };
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
        /*第二步,修改console.c,在开头的定义中添加结构cmdhis及对应的缓冲区cmd_buf 定义 */
        /*对结构体cmdhis进行初始化 */
        /* 代码中略*/
        struct CMDHISTORY cmdhis;
        char cmd_buf[CMDBUF];
        /* 代码中略*/
        cmdhis.buf = cmd_buf;
        cmdhis.argv = (char **)cmd_buf;
        *cmdhis.argv = cmdhis.buf;
        cmdhis.first = 0;
        cmdhis.last = 0;
        cmdhis.head = CMDHIS_NR * 4;
        cmdhis.tail = 0; /* not use but we reserving it */
        cmdhis.now = 0;
        /* 代码中略 */
        /* 在处理键盘接收数据的键盘值-回车键 */
        } else if (i == 10 + 256) {
        cons_putchar(&cons, ' ', 0);
        cmdline[cons.cur_x / 8 - 2] = 0;
        /* 在以下添加如下代码 */
        if (cmdline[0] != 0) {
        if (cmdhis.head+strlen(cmdline)+1 >= CMDBUF) {
        cmdhis.head = CMDHIS_NR << 2;
        }
        if ((unsigned int)(cmdhis.buf + cmdhis.head) <=
        (unsigned int)*(cmdhis.argv + cmdhis.last) &&
        cmdhis.first != cmdhis.last) {
        while ((unsigned int)(cmdhis.buf + cmdhis.head) +
        strlen(cmdline) + 1 >
        (unsigned int)*(cmdhis.argv + cmdhis.last)) {
        if (++cmdhis.last == CMDHIS_NR) cmdhis.last = 0;
        if (cmdhis.last == cmdhis.first) break;
        }
        }
        strcpy(cmdhis.buf + cmdhis.head, cmdline);
        *(cmdhis.argv + cmdhis.first) = cmdhis.buf + cmdhis.head;
        cmdhis.head = cmdhis.head + strlen(cmdline) + 1;
        cmdhis.now = cmdhis.first;
        if(++cmdhis.first == CMDHIS_NR) cmdhis.first = 0;
        if(cmdhis.last == cmdhis.first) {
        if(++cmdhis.last == CMDHIS_NR) cmdhis.last = 0;
        }
        *(cmdhis.argv + cmdhis.first) = 0;
        }
        /* 回车键功能添加语句到此结束
        cons_newline(&cons);
        cons_runcmd(cmdline, &cons, fat, memtotal);
        cons_putchar(&cons, '>', 1);
        /* 下面的两个分支就是添加的处理向上方向键及向下方向键语句 */
        /* 语句模仿console中回车键的处理,即由bootpack.c中将接收到的向上方向键、向下方向键
        转化为,18和20后然后再在下面的语句中对18和20进行分别处理 */
        } else if (i == 18 + 256 && (*(cmdhis.argv+cmdhis.now) != 0)) {
        cmdhis.now--;
        if(cmdhis.first < cmdhis.last && cmdhis.now < 0)
        cmdhis.now = CMDHIS_NR-1;
        if(cmdhis.now < cmdhis.last)
        cmdhis.now = cmdhis.last;
        if(*(cmdhis.argv+cmdhis.now) != 0) {
        while(cons.cur_x > 16) {
        cons_putchar(&cons, ' ', 0);
        cons.cur_x -= 8;
        }
        cons_putstr0(&cons, *(cmdhis.argv + cmdhis.now));
        strcpy(cmdline, *(cmdhis.argv+cmdhis.now));
        }
        } else if (i == 20 + 256 && (*(cmdhis.argv+cmdhis.now) != 0)) {
        cmdhis.now++;
        if(cmdhis.now == cmdhis.first) cmdhis.now--;
        if(cmdhis.now == CMDHIS_NR){
        if(cmdhis.first == 0) {
        cmdhis.now--;
        }else {
        cmdhis.now = 0;
        }
        }
        if(*(cmdhis.argv+cmdhis.now) != 0) {
        while(cons.cur_x > 16) {
        cons_putchar(&cons, ' ', 0);
        cons.cur_x -= 8;
        }
        cons_putstr0(&cons, *(cmdhis.argv + cmdhis.now));
        strcpy(cmdline, *(cmdhis.argv+cmdhis.now));
        }
        }
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
        /* 第三步,修改 bootpack.c文件
        首先就是修改键盘编码。不知道诸位在之前使用过程中发现没有,书上给出的键盘处理有些键盘值和
        我们现在使用的稍微有所不同。因为作者使用的日文键盘的缘故吧,于是我对照我的键盘改了下。
        其实对于键盘修改,如果只需要实现向上向下方向键调出历史命令的话。
        那么只需要将static char keytable0[0x80] 中的第0x48位及0x50位改为0即可。
        keytable1都不用改,毕竟我们这里只是实验而已。这里如果不改的话也可以,只是显示。。。
        不改键盘码也可以,只是显示的时候稍微有点问题,在显示命令的前面会有数字。
        当然此次对应键盘编码不只是方向键还有一些之前日文键盘对应字符我也改了一下位置。
        */
        static char keytable0[0x80] = {
        0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0, 0,
        'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '[', ']', 0, 0, 'A', 'S',
        'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', '\'', '`', 0, '\\', 'Z', 'X', 'C', 'V',
        'B', 'N', 'M', ',', '.', '/', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, '7', 0, '9', '-', '4', '5', '6', '+', '1',
        0, '3', '0', '.', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0x5c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0,
        };
        static char keytable1[0x80] = {
        0, 0, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 0, 0,
        'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 0, 0, 'A', 'S',
        'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '|', 'Z', 'X', 'C', 'V',
        'B', 'N', 'M', '<', '>', '?', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, '7', '8', '9', '-', '4', '5', '6', '+', '1',
        '2', '3', '0', '.', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, '_', 0, 0, 0, 0, 0, 0, 0, 0, 0, '|', 0, 0
        };
        /* 代码中略*/
        /* 在处理键盘数据中*/
        if (i == 256 + 0x46) {/* ScrollLokc */
        key_leds ^= 1;
        fifo32_put(&keycmd, KEYCMD_LED);
        fifo32_put(&keycmd, key_leds);
        }
        /* 在处理 ScrollLokc 键的后面添加如下两个键盘处理分支语句即可 */
        if (i == 256 + 0x48) {
        if (key_to != 0) fifo32_put(&task_cons->fifo, 18 + 256);
        }
        if (i == 256 + 0x50) {
        if (key_to != 0) fifo32_put(&task_cons->fifo, 20 + 256);
        }
        /* 代码中略*/
        /* 如上处理后即可使用命令历史记录了 ,当然基本功能有了。还需要改进,加油 */


        IP属地:四川4楼2015-11-29 18:52
        回复
          不错,到了这里。命令历史记录就算是搞定了。大家随便移植

          上图是我输入的之前输入过的fffff, 看到红色 D0 这个就是向下方向键0x50 释放按键后的键盘码。


          IP属地:四川6楼2015-11-29 19:28
          回复
            /* 在console.c中发现BUG,修改如下 */
            /* 代码中略*/
            } else if (i == 10 + 256) {
            cons_putchar(&cons, ' ', 0);
            cmdline[cons.cur_x / 8 - 2] = 0;
            if (cmdline[0] != 0) {
            if (cmdhis.head+strlen(cmdline)+1 >= CMDBUF) {
            cmdhis.head = CMDHIS_NR << 2;
            }
            if ((unsigned int)(cmdhis.buf + cmdhis.head) <=
            (unsigned int)*(cmdhis.argv + cmdhis.last) &&
            cmdhis.first != cmdhis.last) {
            while ((unsigned int)(cmdhis.buf + cmdhis.head) +
            strlen(cmdline) + 1 >
            (unsigned int)*(cmdhis.argv + cmdhis.last)) {
            if (++cmdhis.last == CMDHIS_NR) cmdhis.last = 0;
            if (cmdhis.last == cmdhis.first) break;
            }
            }
            strcpy(cmdhis.buf + cmdhis.head, cmdline);
            *(cmdhis.argv + cmdhis.first) = cmdhis.buf + cmdhis.head;
            cmdhis.head = cmdhis.head + strlen(cmdline) + 1;
            cmdhis.now = cmdhis.first;
            if(++cmdhis.first == CMDHIS_NR) cmdhis.first = 0;
            if(cmdhis.last == cmdhis.first) {
            if(++cmdhis.last == CMDHIS_NR) cmdhis.last = 0;
            }
            *(cmdhis.argv + cmdhis.first) = 0;
            }
            cons_newline(&cons);
            cons_runcmd(cmdline, &cons, fat, memtotal);
            cons_putchar(&cons, '>', 1);
            } else if (i == 18 + 256 && (*(cmdhis.argv+cmdhis.now) != 0)) {
            while(cons.cur_x > 16) {
            cons_putchar(&cons, ' ', 0);
            cons.cur_x -= 8;
            }
            cons_putstr0(&cons, *(cmdhis.argv + cmdhis.now));
            strcpy(cmdline, *(cmdhis.argv+cmdhis.now));
            if(cmdhis.now == cmdhis.last) cmdhis.now++;
            cmdhis.now--;
            if(cmdhis.first < cmdhis.last && cmdhis.now < 0)
            cmdhis.now = CMDHIS_NR-1;
            } else if (i == 20 + 256 && (*(cmdhis.argv+cmdhis.now) != 0)) {
            while(cons.cur_x > 16) {
            cons_putchar(&cons, ' ', 0);
            cons.cur_x -= 8;
            }
            cons_putstr0(&cons, *(cmdhis.argv + cmdhis.now));
            strcpy(cmdline, *(cmdhis.argv+cmdhis.now));
            cmdhis.now++;
            if(cmdhis.now == cmdhis.first) cmdhis.now--;
            if(cmdhis.now == CMDHIS_NR){
            if(cmdhis.first == 0) {
            cmdhis.now--;
            }else {
            cmdhis.now = 0;
            }
            }
            }
            /* 代码中略*/


            IP属地:四川7楼2015-11-29 19:42
            回复
              本人实测上面代码历史命令区容纳31个命令。未对命令长度做限制。毕竟halibote的一个命令最长为29个字符。命令输入时都未对命令长度做检测,我们后面的也就不用了。请大家随便使用缓冲区溢出。上面的命令历史功能有一个BUG就是 在显示到历史记录头及尾时,上下方向键要按两次才能继续移动。对于这个问题,暂时不想改了,抽空再来。


              IP属地:四川8楼2015-11-29 19:50
              回复
                这个功能要顶上去


                IP属地:四川来自Android客户端9楼2016-07-31 10:12
                回复
                  楼主好人,在第一天时写的这份代码copy helloos.img ..\z_tools\qemu\fdimage0.bin
                  ..\z_tools\make.exe-C ../z_tools/qemu格式看不懂啊,这到底是什么格式啊


                  IP属地:广西10楼2016-07-31 15:20
                  收起回复
                    修改键盘键码的操作会导致tview等场景无法使用方向键控制


                    IP属地:黑龙江11楼2024-01-12 01:25
                    回复