Changeset 0c8e692 in mainline for generic/src/console/kconsole.c


Ignore:
Timestamp:
2005-12-11T19:55:56Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
3550c393
Parents:
54aff98
Message:

Added some readline functionality to kconsole.
Arrows editing, history, tab completion.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • generic/src/console/kconsole.c

    r54aff98 r0c8e692  
    7070static cmd_info_t *parse_cmdline(char *cmdline, size_t len);
    7171static bool parse_argument(char *cmdline, size_t len, index_t *start, index_t *end);
     72static char history[KCONSOLE_HISTORY][MAX_CMDLINE] = {};
    7273
    7374/** Initialize kconsole data structures. */
    7475void kconsole_init(void)
    7576{
     77        int i;
     78
    7679        spinlock_initialize(&cmd_lock, "kconsole_cmd");
    7780        list_initialize(&cmd_head);
    7881
    7982        cmd_init();
     83        for (i=0; i<KCONSOLE_HISTORY; i++)
     84                history[i][0] = '\0';
    8085}
    8186
     
    138143}
    139144
     145static void rdln_print_c(char ch, int count)
     146{
     147        int i;
     148        for (i=0;i<count;i++)
     149                putchar(ch);
     150}
     151
     152static void insert_char(char *str, char ch, int pos)
     153{
     154        int i;
     155       
     156        for (i=strlen(str);i > pos; i--)
     157                str[i] = str[i-1];
     158        str[pos] = ch;
     159}
     160
     161static const char * cmdtab_search_one(const char *name,link_t **startpos)
     162{
     163        int namelen = strlen(name);
     164        const char *curname;
     165        char *foundsym = NULL;
     166        int foundpos = 0;
     167
     168        spinlock_lock(&cmd_lock);
     169
     170        if (!*startpos)
     171                *startpos = cmd_head.next;
     172
     173        for (;*startpos != &cmd_head;*startpos = (*startpos)->next) {
     174                cmd_info_t *hlp;
     175                hlp = list_get_instance(*startpos, cmd_info_t, link);
     176
     177                curname = hlp->name;
     178                if (strlen(curname) < namelen)
     179                        continue;
     180                if (strncmp(curname, name, namelen) == 0) {
     181                        spinlock_unlock(&cmd_lock);     
     182                        return curname+namelen;
     183                }
     184        }
     185        spinlock_unlock(&cmd_lock);     
     186        return NULL;
     187}
     188
     189
     190/** Command completion of the commands
     191 *
     192 * @param name - string to match, changed to hint on exit
     193 * @return number of found matches
     194 */
     195static int cmdtab_compl(char *name)
     196{
     197        char output[MAX_SYMBOL_NAME+1];
     198        link_t *startpos = NULL;
     199        const char *foundtxt;
     200        int found = 0;
     201        int i;
     202
     203        output[0] = '\0';
     204        while ((foundtxt = cmdtab_search_one(name, &startpos))) {
     205                startpos = startpos->next;
     206                if (!found)
     207                        strncpy(output, foundtxt, strlen(foundtxt)+1);
     208                else {
     209                        for (i=0; output[i] && foundtxt[i] && output[i]==foundtxt[i]; i++)
     210                                ;
     211                        output[i] = '\0';
     212                }
     213                found++;
     214        }
     215        if (!found)
     216                return 0;
     217
     218        if (found > 1) {
     219                printf("\n");
     220                startpos = NULL;
     221                while ((foundtxt = cmdtab_search_one(name, &startpos))) {
     222                        cmd_info_t *hlp;
     223                        hlp = list_get_instance(startpos, cmd_info_t, link);
     224                        printf("%s - %s\n", hlp->name, hlp->description);
     225                        startpos = startpos->next;
     226                }
     227        }
     228        strncpy(name, output, MAX_SYMBOL_NAME);
     229        return found;
     230       
     231}
     232
     233static char * clever_readline(const char *prompt, chardev_t *input)
     234{
     235        static int histposition = 0;
     236
     237        char tmp[MAX_CMDLINE+1];
     238        int curlen = 0, position = 0;
     239        char *current = history[histposition];
     240        int i;
     241        char c;
     242
     243        printf("%s> ", prompt);
     244        while (1) {
     245                c = _getc(input);
     246                if (c == '\n') {
     247                        putchar(c);
     248                        break;
     249                } if (c == '\b') {
     250                        if (position == 0)
     251                                continue;
     252                        for (i=position; i<curlen;i++)
     253                                current[i-1] = current[i];
     254                        curlen--;
     255                        position--;
     256                        putchar('\b');
     257                        for (i=position;i<curlen;i++)
     258                                putchar(current[i]);
     259                        putchar(' ');
     260                        rdln_print_c('\b',curlen-position+1);
     261                        continue;
     262                }
     263                if (c == '\t') {
     264                        int found;
     265
     266                        /* Move to the end of the word */
     267                        for (;position<curlen && current[position]!=' ';position++)
     268                                putchar(current[position]);
     269                        /* Copy to tmp last word */
     270                        for (i=position-1;i >= 0 && current[i]!=' ' ;i--)
     271                                ;
     272                        /* If word begins with * or &, skip it */
     273                        if (tmp[0] == '*' || tmp[0] == '&')
     274                                for (i=1;tmp[i];i++)
     275                                        tmp[i-1] = tmp[i];
     276                        i++; /* I is at the start of the word */
     277                        strncpy(tmp, current+i, position-i+1);
     278
     279                        if (i==0) { /* Command completion */
     280                                found = cmdtab_compl(tmp);
     281                        } else { /* Symtab completion */
     282                                found = symtab_compl(tmp);
     283                        }
     284
     285                        if (found == 0)
     286                                continue;
     287                        for (i=0;tmp[i] && curlen < MAX_CMDLINE;i++,curlen++)
     288                                insert_char(current, tmp[i], i+position);
     289                        if (found == 1) { /* One match */
     290                                for (i=position;i<curlen;i++)
     291                                        putchar(current[i]);
     292                                position += strlen(tmp);
     293                                /* Add space to end */
     294                                if (position == curlen && curlen < MAX_CMDLINE) {
     295                                        current[position] = ' ';
     296                                        curlen++;
     297                                        position++;
     298                                        putchar(' ');
     299                                }
     300                        } else {
     301                                printf("%s> ", prompt);
     302                                for (i=0; i<curlen;i++)
     303                                        putchar(current[i]);
     304                                position += strlen(tmp);
     305                        }
     306                        rdln_print_c('\b', curlen-position);
     307                        continue;
     308                }
     309                if (c == 0x1b) {
     310                        c = _getc(input);
     311                        if (c!= 0x5b)
     312                                continue;
     313                        c = _getc(input);
     314                        if (c == 0x44) { /* Left */
     315                                if (position > 0) {
     316                                        putchar('\b');
     317                                        position--;
     318                                }
     319                                continue;
     320                        }
     321                        if (c == 0x43) { /* Right */
     322                                if (position < curlen) {
     323                                        putchar(current[position]);
     324                                        position++;
     325                                }
     326                                continue;
     327                        }
     328                        if (c == 0x41 || c == 0x42) { /* Up,down */
     329                                rdln_print_c('\b',position);
     330                                rdln_print_c(' ',curlen);
     331                                rdln_print_c('\b',curlen);
     332                                if (c == 0x41)
     333                                        histposition--;
     334                                else
     335                                        histposition++;
     336                                if (histposition < 0)
     337                                        histposition = KCONSOLE_HISTORY -1 ;
     338                                else
     339                                        histposition =  histposition % KCONSOLE_HISTORY;
     340                                current = history[histposition];
     341                                printf("%s", current);
     342                                curlen = strlen(current);
     343                                position = curlen;
     344                                continue;
     345                        }
     346                        continue;
     347                }
     348                if (curlen >= MAX_CMDLINE)
     349                        continue;
     350
     351                insert_char(current, c, position);
     352
     353                curlen++;
     354                for (i=position;i<curlen;i++)
     355                        putchar(current[i]);
     356                position++;
     357                rdln_print_c('\b',curlen-position);
     358        }
     359        histposition++;
     360        histposition = histposition % KCONSOLE_HISTORY;
     361        current[curlen] = '\0';
     362        return current;
     363}
     364
    140365/** Kernel console managing thread.
    141366 *
     
    144369void kconsole(void *arg)
    145370{
    146         char cmdline[MAX_CMDLINE+1];
    147371        cmd_info_t *cmd_info;
    148372        count_t len;
     373        char *cmdline;
    149374
    150375        if (!stdin) {
     
    154379       
    155380        while (true) {
    156                 printf("%s> ", __FUNCTION__);
    157                 if (!(len = gets(stdin, cmdline, sizeof(cmdline))))
    158                         continue;
    159                 cmdline[len] = '\0';
     381                cmdline = clever_readline(__FUNCTION__, stdin);
     382                len = strlen(cmdline);
     383                if (!len)
     384                        continue;
    160385                cmd_info = parse_cmdline(cmdline, len);
    161386                if (!cmd_info)
Note: See TracChangeset for help on using the changeset viewer.