Changeset d6c8ff6 in mainline


Ignore:
Timestamp:
2009-04-03T07:58:42Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c583970
Parents:
20cc877
Message:

kconsole cleanup, string changes, Unicode support

Location:
kernel/generic
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/console/kconsole.h

    r20cc877 rd6c8ff6  
    4040#include <ipc/irq.h>
    4141
    42 #define MAX_CMDLINE     256
    43 #define KCONSOLE_HISTORY 10
     42#define MAX_CMDLINE       256
     43#define KCONSOLE_HISTORY  10
    4444
    4545typedef enum {
     
    4848        ARG_TYPE_STRING,
    4949        /** Variable type - either symbol or string. */
    50         ARG_TYPE_VAR     
     50        ARG_TYPE_VAR
    5151} cmd_arg_type_t;
    5252
     
    9797extern void kconsole_thread(void *data);
    9898
    99 extern int cmd_register(cmd_info_t *cmd);
     99extern bool cmd_register(cmd_info_t *cmd);
    100100
    101101#endif
  • kernel/generic/src/console/kconsole.c

    r20cc877 rd6c8ff6  
    3232
    3333/**
    34  * @file        kconsole.c
    35  * @brief       Kernel console.
     34 * @file  kconsole.c
     35 * @brief Kernel console.
    3636 *
    3737 * This file contains kernel thread managing the kernel console.
     38 *
    3839 */
    3940
     
    5758#include <errno.h>
    5859#include <putchar.h>
     60#include <string.h>
    5961
    6062/** Simple kernel console.
     
    6567 * register their own commands.
    6668 */
    67  
     69
    6870/** Locking.
    6971 *
     
    8082 * lower address must be locked first.
    8183 */
    82  
    83 SPINLOCK_INITIALIZE(cmd_lock);  /**< Lock protecting command list. */
    84 LIST_INITIALIZE(cmd_head);      /**< Command list. */
    85 
    86 static cmd_info_t *parse_cmdline(char *cmdline, size_t len);
    87 static bool parse_argument(char *cmdline, size_t len, index_t *start,
    88     index_t *end);
    89 static char history[KCONSOLE_HISTORY][MAX_CMDLINE] = {};
     84
     85SPINLOCK_INITIALIZE(cmd_lock);  /**< Lock protecting command list. */
     86LIST_INITIALIZE(cmd_head);      /**< Command list. */
     87
     88static wchar_t history[KCONSOLE_HISTORY][MAX_CMDLINE] = {};
     89static count_t history_pos = 0;
    9090
    9191/** Initialize kconsole data structures
     
    9898{
    9999        unsigned int i;
    100 
     100       
    101101        cmd_init();
    102102        for (i = 0; i < KCONSOLE_HISTORY; i++)
    103                 history[i][0] = '\0';
     103                history[i][0] = 0;
    104104}
    105105
     
    108108 * @param cmd Structure describing the command.
    109109 *
    110  * @return 0 on failure, 1 on success.
    111  */
    112 int cmd_register(cmd_info_t *cmd)
     110 * @return False on failure, true on success.
     111 *
     112 */
     113bool cmd_register(cmd_info_t *cmd)
    113114{
    114115        link_t *cur;
     
    120121         */
    121122        for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
    122                 cmd_info_t *hlp;
    123                
    124                 hlp = list_get_instance(cur, cmd_info_t, link);
    125 
     123                cmd_info_t *hlp = list_get_instance(cur, cmd_info_t, link);
     124               
    126125                if (hlp == cmd) {
    127126                        /* The command is already there. */
    128127                        spinlock_unlock(&cmd_lock);
    129                         return 0;
    130                 }
    131 
     128                        return false;
     129                }
     130               
    132131                /* Avoid deadlock. */
    133132                if (hlp < cmd) {
     
    138137                        spinlock_lock(&hlp->lock);
    139138                }
    140                 if ((strncmp(hlp->name, cmd->name, max(str_size(cmd->name),
    141                     str_size(hlp->name))) == 0)) {
     139               
     140                if (str_cmp(hlp->name, cmd->name) == 0) {
    142141                        /* The command is already there. */
    143142                        spinlock_unlock(&hlp->lock);
    144143                        spinlock_unlock(&cmd->lock);
    145144                        spinlock_unlock(&cmd_lock);
    146                         return 0;
     145                        return false;
    147146                }
    148147               
     
    157156       
    158157        spinlock_unlock(&cmd_lock);
    159         return 1;
     158        return true;
    160159}
    161160
    162161/** Print count times a character */
    163 static void rdln_print_c(wchar_t ch, count_t count)
     162static void print_cc(wchar_t ch, count_t count)
    164163{
    165164        count_t i;
     
    168167}
    169168
    170 /** Insert character to string */
    171 static void insert_char(char *str, char ch, int pos)
    172 {
    173         int i;
    174        
    175         for (i = str_size(str); i > pos; i--)
    176                 str[i] = str[i - 1];
    177         str[pos] = ch;
    178 }
    179 
    180169/** Try to find a command beginning with prefix */
    181 static const char *cmdtab_search_one(const char *name,link_t **startpos)
    182 {
    183         size_t namelen = str_size(name);
    184         const char *curname;
    185 
     170static const char *cmdtab_search_one(const char *name, link_t **startpos)
     171{
     172        count_t namelen = str_length(name);
     173       
    186174        spinlock_lock(&cmd_lock);
    187 
    188         if (!*startpos)
     175       
     176        if (*startpos == NULL)
    189177                *startpos = cmd_head.next;
    190 
     178       
    191179        for (; *startpos != &cmd_head; *startpos = (*startpos)->next) {
    192                 cmd_info_t *hlp;
    193                 hlp = list_get_instance(*startpos, cmd_info_t, link);
    194 
    195                 curname = hlp->name;
    196                 if (str_size(curname) < namelen)
     180                cmd_info_t *hlp = list_get_instance(*startpos, cmd_info_t, link);
     181               
     182                const char *curname = hlp->name;
     183                if (str_length(curname) < namelen)
    197184                        continue;
    198                 if (strncmp(curname, name, namelen) == 0) {
    199                         spinlock_unlock(&cmd_lock);     
    200                         return curname+namelen;
    201                 }
    202         }
    203         spinlock_unlock(&cmd_lock);     
     185               
     186                if (str_lcmp(curname, name, namelen) == 0) {
     187                        spinlock_unlock(&cmd_lock);
     188                        return (curname + str_lsize(curname, namelen));
     189                }
     190        }
     191       
     192        spinlock_unlock(&cmd_lock);
    204193        return NULL;
    205194}
    206195
    207 
    208 /** Command completion of the commands
    209  *
    210  * @param name - string to match, changed to hint on exit
    211  * @return number of found matches
    212  */
    213 static int cmdtab_compl(char *name)
    214 {
    215         static char output[/*MAX_SYMBOL_NAME*/128 + 1];
    216         link_t *startpos = NULL;
    217         const char *foundtxt;
    218         int found = 0;
    219         int i;
    220 
    221         output[0] = '\0';
    222         while ((foundtxt = cmdtab_search_one(name, &startpos))) {
    223                 startpos = startpos->next;
    224                 if (!found)
    225                         strncpy(output, foundtxt, str_size(foundtxt) + 1);
    226                 else {
    227                         for (i = 0; output[i] && foundtxt[i] &&
    228                             output[i] == foundtxt[i]; i++)
    229                                 ;
    230                         output[i] = '\0';
    231                 }
     196/** Command completion of the commands
     197 *
     198 * @param name String to match, changed to hint on exit
     199 * @param size Input buffer size
     200 *
     201 * @return Number of found matches
     202 *
     203 */
     204static int cmdtab_compl(char *input, size_t size)
     205{
     206        const char *name = input;
     207       
     208        count_t found = 0;
     209        link_t *pos = NULL;
     210        const char *hint;
     211        char output[MAX_CMDLINE];
     212       
     213        output[0] = 0;
     214       
     215        while ((hint = cmdtab_search_one(name, &pos))) {
     216                if ((found == 0) || (str_length(output) > str_length(hint)))
     217                        str_ncpy(output, hint, MAX_CMDLINE);
     218               
     219                pos = pos->next;
    232220                found++;
    233221        }
    234         if (!found)
    235                 return 0;
    236 
    237         if (found > 1 && !str_size(output)) {
     222       
     223        if ((found > 1) && (str_length(output) != 0)) {
    238224                printf("\n");
    239                 startpos = NULL;
    240                 while ((foundtxt = cmdtab_search_one(name, &startpos))) {
    241                         cmd_info_t *hlp;
    242                         hlp = list_get_instance(startpos, cmd_info_t, link);
    243                         printf("%s - %s\n", hlp->name, hlp->description);
    244                         startpos = startpos->next;
    245                 }
    246         }
    247         strncpy(name, output, 128/*MAX_SYMBOL_NAME*/);
     225                pos = NULL;
     226                while ((hint = cmdtab_search_one(name, &pos))) {
     227                        cmd_info_t *hlp = list_get_instance(pos, cmd_info_t, link);
     228                        printf("%s (%s)\n", hlp->name, hlp->description);
     229                        pos = pos->next;
     230                }
     231        }
     232       
     233        if (found > 0)
     234                str_ncpy(input, output, size);
     235       
    248236        return found;
    249237}
    250238
    251 static char *clever_readline(const char *prompt, indev_t *input)
    252 {
    253         static int histposition = 0;
    254 
    255         static char tmp[MAX_CMDLINE + 1];
    256         int curlen = 0, position = 0;
    257         char *current = history[histposition];
    258         int i;
    259         char mod; /* Command Modifier */
    260         char c;
    261 
     239static wchar_t *clever_readline(const char *prompt, indev_t *indev)
     240{
    262241        printf("%s> ", prompt);
    263         while (1) {
    264                 c = _getc(input);
    265                 if (c == '\n') {
    266                         putchar(c);
     242       
     243        count_t position = 0;
     244        wchar_t *current = history[history_pos];
     245        current[0] = 0;
     246       
     247        while (true) {
     248                wchar_t ch = _getc(indev);
     249               
     250                if (ch == '\n') {
     251                        /* Enter */
     252                        putchar(ch);
    267253                        break;
    268254                }
    269                 if (c == '\b') { /* Backspace */
     255               
     256                if (ch == '\b') {
     257                        /* Backspace */
    270258                        if (position == 0)
    271259                                continue;
    272                         for (i = position; i < curlen; i++)
    273                                 current[i - 1] = current[i];
    274                         curlen--;
    275                         position--;
    276                         putchar('\b');
    277                         for (i = position; i < curlen; i++)
    278                                 putchar(current[i]);
    279                         putchar(' ');
    280                         rdln_print_c('\b', curlen - position + 1);
    281                         continue;
    282                 }
    283                 if (c == '\t') { /* Tabulator */
    284                         int found;
    285 
     260                       
     261                        if (wstr_remove(current, position - 1)) {
     262                                putchar('\b');
     263                                printf("%ls", current + position);
     264                                position--;
     265                                print_cc('\b', wstr_length(current) - position);
     266                                continue;
     267                        }
     268                }
     269               
     270                if (ch == '\t') {
     271                        /* Tab completion */
     272                       
    286273                        /* Move to the end of the word */
    287                         for (; position < curlen && current[position] != ' ';
     274                        for (; (current[position] != 0) && (!isspace(current[position]));
    288275                            position++)
    289276                                putchar(current[position]);
    290                         /* Copy to tmp last word */
    291                         for (i = position - 1; i >= 0 && current[i] != ' '; i--)
    292                                 ;
    293                         /* If word begins with * or &, skip it */
    294                         if (tmp[0] == '*' || tmp[0] == '&')
    295                                 for (i = 1; tmp[i]; i++)
    296                                         tmp[i - 1] = tmp[i];
    297                         i++; /* I is at the start of the word */
    298                         strncpy(tmp, current + i, position - i + 1);
    299 
    300                         if (i == 0) { /* Command completion */
    301                                 found = cmdtab_compl(tmp);
    302                         } else { /* Symtab completion */
    303                                 found = symtab_compl(tmp);
     277                       
     278                        if (position == 0)
     279                                continue;
     280                       
     281                        /* Find the beginning of the word
     282                           and copy it to tmp */
     283                        count_t beg;
     284                        for (beg = position - 1; (beg > 0) && (!isspace(current[beg]));
     285                            beg--);
     286                       
     287                        if (isspace(current[beg]))
     288                                beg++;
     289                       
     290                        char tmp[STR_BOUNDS(MAX_CMDLINE)];
     291                        wstr_nstr(tmp, current + beg, position - beg + 1);
     292                       
     293                        int found;
     294                        if (beg == 0) {
     295                                /* Command completion */
     296                                found = cmdtab_compl(tmp, STR_BOUNDS(MAX_CMDLINE));
     297                        } else {
     298                                /* Symbol completion */
     299                                found = symtab_compl(tmp, STR_BOUNDS(MAX_CMDLINE));
    304300                        }
    305 
    306                         if (found == 0) 
     301                       
     302                        if (found == 0)
    307303                                continue;
    308                         for (i = 0; tmp[i] && curlen < MAX_CMDLINE;
    309                             i++, curlen++)
    310                                 insert_char(current, tmp[i], i + position);
    311 
    312                         if (str_size(tmp) || found == 1) { /* If we have a hint */
    313                                 for (i = position; i < curlen; i++)
    314                                         putchar(current[i]);
    315                                 position += str_size(tmp);
    316                                 /* Add space to end */
    317                                 if (found == 1 && position == curlen &&
    318                                     curlen < MAX_CMDLINE) {
    319                                         current[position] = ' ';
    320                                         curlen++;
    321                                         position++;
    322                                         putchar(' ');
     304                       
     305                        size_t off = 0;
     306                        count_t i = 0;
     307                        while ((ch = str_decode(tmp, &off, STR_NO_LIMIT)) != 0) {
     308                                if (!wstr_linsert(current, ch, position + i, MAX_CMDLINE))
     309                                        break;
     310                                i++;
     311                        }
     312                       
     313                        if ((str_length(tmp) > 0) || (found == 1)) {
     314                                /* We have a hint */
     315                                printf("%ls", current + position);
     316                                print_cc('\b', wstr_length(current) - position);
     317                                position += str_length(tmp);
     318                               
     319                                if ((found == 1) && (position == wstr_length(current))) {
     320                                        if (wstr_linsert(current, ' ', position, MAX_CMDLINE)) {
     321                                                printf("%ls", current + position);
     322                                                position++;
     323                                        }
    323324                                }
    324                         } else { /* No hint, table was printed */
     325                        } else {
     326                                /* No unique hint, list was printed */
    325327                                printf("%s> ", prompt);
    326                                 for (i = 0; i < curlen; i++)
    327                                         putchar(current[i]);
    328                                 position += str_size(tmp);
     328                                printf("%ls", current);
     329                                position += str_length(tmp);
    329330                        }
    330                         rdln_print_c('\b', curlen - position);
     331                       
     332                        print_cc('\b', wstr_length(current) - position);
    331333                        continue;
    332334                }
    333                 if (c == 0x1b) { /* Special command */
    334                         mod = _getc(input);
    335                         c = _getc(input);
    336 
    337                         if (mod != 0x5b && mod != 0x4f)
     335               
     336                if (ch == 0x1b) {
     337                        /* Special command */
     338                        wchar_t mod = _getc(indev);
     339                        wchar_t ch = _getc(indev);
     340                       
     341                        if ((mod != 0x5b) && (mod != 0x4f))
    338342                                continue;
    339 
    340                         if (c == 0x33 && _getc(input) == 0x7e) {
     343                       
     344                        if ((ch == 0x33) && (_getc(indev) == 0x7e)) {
    341345                                /* Delete */
    342                                 if (position == curlen)
     346                                if (position == wstr_length(current))
    343347                                        continue;
    344                                 for (i = position + 1; i < curlen; i++) {
    345                                         putchar(current[i]);
    346                                         current[i - 1] = current[i];
     348                               
     349                                if (wstr_remove(current, position)) {
     350                                        putchar('\b');
     351                                        printf("%ls", current + position);
     352                                        position--;
     353                                        print_cc('\b', wstr_length(current) - position);
    347354                                }
    348                                 putchar(' ');
    349                                 rdln_print_c('\b', curlen - position);
    350                                 curlen--;
    351                         } else if (c == 0x48) { /* Home */
    352                                 rdln_print_c('\b', position);
     355                        } else if (ch == 0x48) {
     356                                /* Home */
     357                                print_cc('\b', position);
    353358                                position = 0;
    354                         } else if (c == 0x46) {  /* End */
    355                                 for (i = position; i < curlen; i++)
    356                                         putchar(current[i]);
    357                                 position = curlen;
    358                         } else if (c == 0x44) { /* Left */
     359                        } else if (ch == 0x46) {
     360                                /* End */
     361                                printf("%ls", current + position);
     362                                position = wstr_length(current);
     363                        } else if (ch == 0x44) {
     364                                /* Left */
    359365                                if (position > 0) {
    360366                                        putchar('\b');
    361367                                        position--;
    362368                                }
    363                                 continue;
    364                         } else if (c == 0x43) { /* Right */
    365                                 if (position < curlen) {
     369                        } else if (ch == 0x43) {
     370                                /* Right */
     371                                if (position < wstr_length(current)) {
    366372                                        putchar(current[position]);
    367373                                        position++;
    368374                                }
    369                                 continue;
    370                         } else if (c == 0x41 || c == 0x42) {
    371                                 /* Up, down */
    372                                 rdln_print_c('\b', position);
    373                                 rdln_print_c(' ', curlen);
    374                                 rdln_print_c('\b', curlen);
    375                                 if (c == 0x41) /* Up */
    376                                         histposition--;
    377                                 else
    378                                         histposition++;
    379                                 if (histposition < 0) {
    380                                         histposition = KCONSOLE_HISTORY - 1;
     375                        } else if ((ch == 0x41) || (ch == 0x42)) {
     376                                /* Up, down */
     377                                print_cc('\b', position);
     378                                print_cc(' ', wstr_length(current));
     379                                print_cc('\b', wstr_length(current));
     380                               
     381                                if (ch == 0x41) {
     382                                        /* Up */
     383                                        if (history_pos == 0)
     384                                                history_pos = KCONSOLE_HISTORY - 1;
     385                                        else
     386                                                history_pos--;
    381387                                } else {
    382                                         histposition =
    383                                             histposition % KCONSOLE_HISTORY;
     388                                        /* Down */
     389                                        history_pos++;
     390                                        history_pos = history_pos % KCONSOLE_HISTORY;
    384391                                }
    385                                 current = history[histposition];
    386                                 printf("%s", current);
    387                                 curlen = str_size(current);
    388                                 position = curlen;
    389                                 continue;
     392                                current = history[history_pos];
     393                                printf("%ls", current);
     394                                position = wstr_length(current);
    390395                        }
    391396                        continue;
    392397                }
    393                 if (curlen >= MAX_CMDLINE)
    394                         continue;
    395 
    396                 insert_char(current, c, position);
    397 
    398                 curlen++;
    399                 for (i = position; i < curlen; i++)
    400                         putchar(current[i]);
    401                 position++;
    402                 rdln_print_c('\b',curlen - position);
    403         }
    404         if (curlen) {
    405                 histposition++;
    406                 histposition = histposition % KCONSOLE_HISTORY;
    407         }
    408         current[curlen] = '\0';
     398               
     399                if (wstr_linsert(current, ch, position, MAX_CMDLINE)) {
     400                        printf("%ls", current + position);
     401                        position++;
     402                        print_cc('\b', wstr_length(current) - position);
     403                }
     404        }
     405       
     406        if (wstr_length(current) > 0) {
     407                history_pos++;
     408                history_pos = history_pos % KCONSOLE_HISTORY;
     409        }
     410       
    409411        return current;
    410412}
     
    415417}
    416418
    417 /** Kernel console prompt.
    418  *
    419  * @param prompt Kernel console prompt (e.g kconsole/panic).
    420  * @param msg    Message to display in the beginning.
    421  * @param kcon   Wait for keypress to show the prompt
    422  *               and never exit.
    423  *
    424  */
    425 void kconsole(char *prompt, char *msg, bool kcon)
    426 {
    427         cmd_info_t *cmd_info;
    428         count_t len;
    429         char *cmdline;
    430        
    431         if (!stdin) {
    432                 LOG("No stdin for kernel console");
    433                 return;
    434         }
    435        
    436         if (msg)
    437                 printf("%s", msg);
    438        
    439         if (kcon)
    440                 _getc(stdin);
    441         else
    442                 printf("Type \"exit\" to leave the console.\n");
    443        
    444         while (true) {
    445                 cmdline = clever_readline((char *) prompt, stdin);
    446                 len = str_size(cmdline);
    447                 if (!len)
    448                         continue;
    449                
    450                 if ((!kcon) && (len == 4) && (strncmp(cmdline, "exit", 4) == 0))
    451                         break;
    452                
    453                 cmd_info = parse_cmdline(cmdline, len);
    454                 if (!cmd_info)
    455                         continue;
    456                
    457                 (void) cmd_info->func(cmd_info->argv);
    458         }
    459 }
    460 
    461 /** Kernel console managing thread.
    462  *
    463  */
    464 void kconsole_thread(void *data)
    465 {
    466         kconsole("kconsole", "Kernel console ready (press any key to activate)\n", true);
    467 }
    468 
    469 static int parse_int_arg(char *text, size_t len, unative_t *result)
    470 {
    471         uintptr_t symaddr;
     419static bool parse_int_arg(const char *text, size_t len, unative_t *result)
     420{
    472421        bool isaddr = false;
    473422        bool isptr = false;
    474         int rc;
    475 
    476         static char symname[MAX_SYMBOL_NAME];
    477423       
    478424        /* If we get a name, try to find it in symbol table */
     
    486432                len--;
    487433        }
    488         if (text[0] < '0' || text[0] > '9') {
    489                 strncpy(symname, text, min(len + 1, MAX_SYMBOL_NAME));
    490                 rc = symtab_addr_lookup(symname, &symaddr);
     434       
     435        if ((text[0] < '0') || (text[0] > '9')) {
     436                char symname[MAX_SYMBOL_NAME];
     437                str_ncpy(symname, text, min(len + 1, MAX_SYMBOL_NAME));
     438               
     439                uintptr_t symaddr;
     440                int rc = symtab_addr_lookup(symname, &symaddr);
    491441                switch (rc) {
    492442                case ENOENT:
    493443                        printf("Symbol %s not found.\n", symname);
    494                         return -1;
     444                        return false;
    495445                case EOVERFLOW:
    496446                        printf("Duplicate symbol %s.\n", symname);
    497447                        symtab_print_search(symname);
    498                         return -1;
    499                 default:
     448                        return false;
     449                case ENOTSUP:
    500450                        printf("No symbol information available.\n");
    501                         return -1;
    502                 }
    503 
     451                        return false;
     452                }
     453               
    504454                if (isaddr)
    505                         *result = (unative_t)symaddr;
     455                        *result = (unative_t) symaddr;
    506456                else if (isptr)
    507                         *result = **((unative_t **)symaddr);
     457                        *result = **((unative_t **) symaddr);
    508458                else
    509                         *result = *((unative_t *)symaddr);
    510         } else { /* It's a number - convert it */
     459                        *result = *((unative_t *) symaddr);
     460        } else {
     461                /* It's a number - convert it */
    511462                *result = atoi(text);
    512463                if (isptr)
    513                         *result = *((unative_t *)*result);
    514         }
    515 
    516         return 0;
     464                        *result = *((unative_t *) *result);
     465        }
     466       
     467        return true;
     468}
     469
     470/** Parse argument.
     471 *
     472 * Find start and end positions of command line argument.
     473 *
     474 * @param cmdline Command line as read from the input device.
     475 * @param size    Size (in bytes) of the string.
     476 * @param start   On entry, 'start' contains pointer to the offset
     477 *                of the first unprocessed character of cmdline.
     478 *                On successful exit, it marks beginning of the next argument.
     479 * @param end     Undefined on entry. On exit, 'end' is the offset of the first
     480 *                character behind the next argument.
     481 *
     482 * @return False on failure, true on success.
     483 *
     484 */
     485static bool parse_argument(const char *cmdline, size_t size, size_t *start, size_t *end)
     486{
     487        ASSERT(start != NULL);
     488        ASSERT(end != NULL);
     489       
     490        bool found_start = false;
     491        size_t offset = *start;
     492        size_t prev = *start;
     493        wchar_t ch;
     494       
     495        while ((ch = str_decode(cmdline, &offset, size)) != 0) {
     496                if (!found_start) {
     497                        if (!isspace(ch)) {
     498                                *start = prev;
     499                                found_start = true;
     500                        }
     501                } else {
     502                        if (isspace(ch))
     503                                break;
     504                }
     505               
     506                prev = offset;
     507        }
     508        *end = offset;
     509       
     510        return found_start;
    517511}
    518512
    519513/** Parse command line.
    520514 *
    521  * @param cmdline Command line as read from input device.
    522  * @param len Command line length.
     515 * @param cmdline Command line as read from input device. 
     516 * @param size    Size (in bytes) of the string.
    523517 *
    524518 * @return Structure describing the command.
    525  */
    526 cmd_info_t *parse_cmdline(char *cmdline, size_t len)
    527 {
    528         index_t start = 0, end = 0;
     519 *
     520 */
     521static cmd_info_t *parse_cmdline(const char *cmdline, size_t size)
     522{
     523        size_t start = 0;
     524        size_t end = 0;
     525        if (!parse_argument(cmdline, size, &start, &end)) {
     526                /* Command line did not contain alphanumeric word. */
     527                return NULL;
     528        }
     529        spinlock_lock(&cmd_lock);
     530       
    529531        cmd_info_t *cmd = NULL;
    530532        link_t *cur;
    531         count_t i;
    532         int error = 0;
    533        
    534         if (!parse_argument(cmdline, len, &start, &end)) {
    535                 /* Command line did not contain alphanumeric word. */
    536                 return NULL;
    537         }
    538 
    539         spinlock_lock(&cmd_lock);
    540533       
    541534        for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
    542                 cmd_info_t *hlp;
    543                
    544                 hlp = list_get_instance(cur, cmd_info_t, link);
     535                cmd_info_t *hlp = list_get_instance(cur, cmd_info_t, link);
    545536                spinlock_lock(&hlp->lock);
    546537               
    547                 if (strncmp(hlp->name, &cmdline[start], max(str_size(hlp->name),
    548                     end - start + 1)) == 0) {
     538                if (str_lcmp(hlp->name, cmdline + start,
     539                    max(str_length(hlp->name),
     540                    str_nlength(cmdline + start, (count_t) (end - start) - 1))) == 0) {
    549541                        cmd = hlp;
    550542                        break;
     
    554546        }
    555547       
    556         spinlock_unlock(&cmd_lock);     
     548        spinlock_unlock(&cmd_lock);
    557549       
    558550        if (!cmd) {
     
    561553                return NULL;
    562554        }
    563 
     555       
    564556        /* cmd == hlp is locked */
    565557       
     
    570562         * structure.
    571563         */
    572 
     564       
     565        bool error = false;
     566        count_t i;
    573567        for (i = 0; i < cmd->argc; i++) {
    574                 char *buf;
    575                 start = end + 1;
    576                 if (!parse_argument(cmdline, len, &start, &end)) {
     568                start = end;
     569                if (!parse_argument(cmdline, size, &start, &end)) {
    577570                        printf("Too few arguments.\n");
    578571                        spinlock_unlock(&cmd->lock);
     
    580573                }
    581574               
    582                 error = 0;
     575                char *buf;
    583576                switch (cmd->argv[i].type) {
    584577                case ARG_TYPE_STRING:
    585578                        buf = (char *) cmd->argv[i].buffer;
    586                         strncpy(buf, (const char *) &cmdline[start],
    587                             min((end - start) + 2, cmd->argv[i].len));
    588                         buf[min((end - start) + 1, cmd->argv[i].len - 1)] =
    589                             '\0';
     579                        str_ncpy(buf, cmdline + start,
     580                            min((end - start) + 1, cmd->argv[i].len));
    590581                        break;
    591                 case ARG_TYPE_INT: 
    592                         if (parse_int_arg(cmdline + start, end - start + 1,
     582                case ARG_TYPE_INT:
     583                        if (!parse_int_arg(cmdline + start, end - start,
    593584                            &cmd->argv[i].intval))
    594                                 error = 1;
     585                                error = true;
    595586                        break;
    596587                case ARG_TYPE_VAR:
    597                         if (start != end && cmdline[start] == '"' &&
    598                             cmdline[end] == '"') {
    599                                 buf = (char *) cmd->argv[i].buffer;
    600                                 strncpy(buf, (const char *) &cmdline[start + 1],
    601                                     min((end-start), cmd->argv[i].len));
    602                                 buf[min((end - start), cmd->argv[i].len - 1)] =
    603                                     '\0';
    604                                 cmd->argv[i].intval = (unative_t) buf;
    605                                 cmd->argv[i].vartype = ARG_TYPE_STRING;
    606                         } else if (!parse_int_arg(cmdline + start,
    607                             end - start + 1, &cmd->argv[i].intval)) {
     588                        if ((start < end - 1) && (cmdline[start] == '"')) {
     589                                if (cmdline[end - 1] == '"') {
     590                                        buf = (char *) cmd->argv[i].buffer;
     591                                        str_ncpy(buf, cmdline + start + 1,
     592                                            min((end - start) - 1, cmd->argv[i].len));
     593                                        cmd->argv[i].intval = (unative_t) buf;
     594                                        cmd->argv[i].vartype = ARG_TYPE_STRING;
     595                                } else {
     596                                        printf("Wrong synxtax.\n");
     597                                        error = true;
     598                                }
     599                        } else if (parse_int_arg(cmdline + start,
     600                            end - start, &cmd->argv[i].intval)) {
    608601                                cmd->argv[i].vartype = ARG_TYPE_INT;
    609602                        } else {
    610603                                printf("Unrecognized variable argument.\n");
    611                                 error = 1;
     604                                error = true;
    612605                        }
    613606                        break;
    614607                case ARG_TYPE_INVALID:
    615608                default:
    616                         printf("invalid argument type\n");
    617                         error = 1;
     609                        printf("Invalid argument type\n");
     610                        error = true;
    618611                        break;
    619612                }
     
    625618        }
    626619       
    627         start = end + 1;
    628         if (parse_argument(cmdline, len, &start, &end)) {
     620        start = end;
     621        if (parse_argument(cmdline, size, &start, &end)) {
    629622                printf("Too many arguments.\n");
    630623                spinlock_unlock(&cmd->lock);
     
    636629}
    637630
    638 /** Parse argument.
    639  *
    640  * Find start and end positions of command line argument.
    641  *
    642  * @param cmdline Command line as read from the input device.
    643  * @param len Number of characters in cmdline.
    644  * @param start On entry, 'start' contains pointer to the index
    645  *        of first unprocessed character of cmdline.
    646  *        On successful exit, it marks beginning of the next argument.
    647  * @param end Undefined on entry. On exit, 'end' points to the last character
    648  *        of the next argument.
    649  *
    650  * @return false on failure, true on success.
    651  */
    652 bool parse_argument(char *cmdline, size_t len, index_t *start, index_t *end)
    653 {
    654         index_t i;
    655         bool found_start = false;
    656        
    657         ASSERT(start != NULL);
    658         ASSERT(end != NULL);
    659        
    660         for (i = *start; i < len; i++) {
    661                 if (!found_start) {
    662                         if (isspace(cmdline[i]))
    663                                 (*start)++;
    664                         else
    665                                 found_start = true;
    666                 } else {
    667                         if (isspace(cmdline[i]))
    668                                 break;
    669                 }
    670         }
    671         *end = i - 1;
    672 
    673         return found_start;
     631/** Kernel console prompt.
     632 *
     633 * @param prompt Kernel console prompt (e.g kconsole/panic).
     634 * @param msg    Message to display in the beginning.
     635 * @param kcon   Wait for keypress to show the prompt
     636 *               and never exit.
     637 *
     638 */
     639void kconsole(char *prompt, char *msg, bool kcon)
     640{
     641        if (!stdin) {
     642                LOG("No stdin for kernel console");
     643                return;
     644        }
     645       
     646        if (msg)
     647                printf("%s", msg);
     648       
     649        if (kcon)
     650                _getc(stdin);
     651        else
     652                printf("Type \"exit\" to leave the console.\n");
     653       
     654        while (true) {
     655                wchar_t *tmp = clever_readline((char *) prompt, stdin);
     656                count_t len = wstr_length(tmp);
     657                if (!len)
     658                        continue;
     659               
     660                char cmdline[STR_BOUNDS(MAX_CMDLINE)];
     661                wstr_nstr(cmdline, tmp, STR_BOUNDS(MAX_CMDLINE));
     662               
     663                if ((!kcon) && (len == 4) && (str_lcmp(cmdline, "exit", 4) == 0))
     664                        break;
     665               
     666                cmd_info_t *cmd_info = parse_cmdline(cmdline, STR_BOUNDS(MAX_CMDLINE));
     667                if (!cmd_info)
     668                        continue;
     669               
     670                (void) cmd_info->func(cmd_info->argv);
     671        }
     672}
     673
     674/** Kernel console managing thread.
     675 *
     676 */
     677void kconsole_thread(void *data)
     678{
     679        kconsole("kconsole", "Kernel console ready (press any key to activate)\n", true);
    674680}
    675681
Note: See TracChangeset for help on using the changeset viewer.