Home | History | Annotate | Download | only in src
      1 /*
      2  * console.c
      3  *
      4  * Copyright 2001-2009 Texas Instruments, Inc. - http://www.ti.com/
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 
     19 /****************************************************************************
     20 *
     21 *   MODULE:  console.c
     22 *
     23 *   PURPOSE:
     24 *
     25 *   DESCRIPTION:
     26 *   ============
     27 *
     28 *
     29 ****************************************************************************/
     30 
     31 /* includes */
     32 /************/
     33 #include <stdio.h>
     34 #include "cu_osapi.h"
     35 #include "console.h"
     36 #include "cu_cmd.h"
     37 
     38 /* defines */
     39 /***********/
     40 #define INBUF_LENGTH            2100
     41 #define MAX_NAME_LEN        64
     42 #define MAX_HELP_LEN        40
     43 #define MAX_PARM_LEN        20
     44 #define ALIAS_LEN           1
     45 
     46 #define TOKEN_UP           ".."
     47 #define TOKEN_ROOT         "/"
     48 #define TOKEN_BREAK        "#"
     49 #define TOKEN_HELP         "?"
     50 #define TOKEN_DIRHELP      "help"
     51 #define TOKEN_QUIT         "q1"
     52 
     53 /* local types */
     54 /***************/
     55 
     56 typedef enum
     57 {
     58     Dir,
     59     Token
     60 } ConEntry_type_t;
     61 
     62 /* Token types */
     63 typedef enum
     64 {
     65     EmptyToken,
     66     UpToken,
     67     RootToken,
     68     BreakToken,
     69     HelpToken,
     70     DirHelpToken,
     71     QuitToken,
     72     NameToken
     73 } TokenType_t;
     74 
     75 
     76 /* Monitor token structure */
     77 typedef struct ConEntry_t
     78 {
     79     struct ConEntry_t   *next;
     80     S8                  name[MAX_NAME_LEN+1];    /* Entry name */
     81     S8                  help[MAX_HELP_LEN+1];    /* Help string */
     82     PS8                 alias;                  /* Alias - always in upper case*/
     83     ConEntry_type_t     sel;                   /* Entry selector */
     84 
     85     union
     86     {
     87         struct
     88         {
     89             struct ConEntry_t   *upper;            /* Upper directory */
     90             struct ConEntry_t   *first;            /* First entry */
     91         } dir;
     92         struct t_Token
     93         {
     94             FuncToken_t    f_tokenFunc;            /* Token handler */
     95             S32            totalParams;
     96             ConParm_t      *parm;                  /* Parameters array with totalParams size */
     97             PS8            *name;                 /* Parameter name with totalParams size */
     98         } token;
     99     } u;
    100 } ConEntry_t;
    101 
    102 /* Module control block */
    103 typedef struct Console_t
    104 {
    105     THandle hCuCmd;
    106 
    107     S32 isDeviceOpen;
    108 
    109     ConEntry_t *p_mon_root;
    110     ConEntry_t *p_cur_dir;
    111     PS8         p_inbuf;
    112     volatile S32 stop_UI_Monitor;
    113 } Console_t;
    114 
    115 /* local variables */
    116 /*******************/
    117 
    118 /* local fucntions */
    119 /*******************/
    120 static VOID Console_allocRoot(Console_t* pConsole);
    121 int consoleRunScript( char *script_file, THandle hConsole);
    122 
    123 
    124 /* Remove leading blanks */
    125 static PS8 Console_ltrim(PS8 s)
    126 {
    127     while( *s == ' ' || *s == '\t' ) s++;
    128     return s;
    129 }
    130 
    131 /*
    132 Make a preliminary analizis of <name> token.
    133 Returns a token type (Empty, Up, Root, Break, Name)
    134 */
    135 static TokenType_t Console_analizeToken( PS8 name )
    136 {
    137     if (!name[0])
    138         return EmptyToken;
    139 
    140     if (!os_strcmp(name, (PS8)TOKEN_UP ) )
    141         return UpToken;
    142 
    143     if (!os_strcmp(name, (PS8)TOKEN_ROOT ) )
    144         return RootToken;
    145 
    146     if (!os_strcmp(name, (PS8)TOKEN_BREAK ) )
    147         return BreakToken;
    148 
    149     if (!os_strcmp(name, (PS8)TOKEN_HELP ) )
    150         return HelpToken;
    151 
    152     if (!os_strcmp(name, (PS8)TOKEN_DIRHELP ) )
    153         return DirHelpToken;
    154 
    155     if (!os_strcmp(name, (PS8)TOKEN_QUIT ) )
    156         return QuitToken;
    157 
    158     return NameToken;
    159 
    160 }
    161 
    162 /* Compare strings case insensitive */
    163 static S32 Console_stricmp( PS8 s1, PS8 s2, U16 len )
    164 {
    165     S32  i;
    166 
    167     for( i=0; i<len && s1[i] && s2[i]; i++ )
    168     {
    169         if (os_tolower(s1[i])  != os_tolower(s2[i] ))
    170             break;
    171     }
    172 
    173     return ( (len - i) * (s1[i] - s2[i]) );
    174 }
    175 
    176 /* Convert string s to lower case. Return pointer to s */
    177 static PS8 Console_strlwr( PS8 s )
    178 {
    179     PS8 s0=s;
    180 
    181     while( *s )
    182     {
    183         *s = (S8)os_tolower(*s );
    184         ++s;
    185     }
    186 
    187     return s0;
    188 }
    189 
    190 /* free the entries tree */
    191 static VOID Console_FreeEntry(ConEntry_t *pEntry)
    192 {
    193     ConEntry_t *pEntryTemp,*pEntryTemp1;
    194 
    195     if(pEntry->sel == Dir)
    196     {
    197         pEntryTemp = pEntry->u.dir.first;
    198 
    199         while (pEntryTemp)
    200         {
    201             pEntryTemp1 = pEntryTemp->next;
    202             Console_FreeEntry(pEntryTemp);
    203             pEntryTemp = pEntryTemp1;
    204         }
    205     }
    206 
    207     /* free the current entry */
    208     os_MemoryFree(pEntry);
    209 }
    210 
    211 
    212 /* Allocate root directory */
    213 static VOID Console_allocRoot(Console_t* pConsole)
    214 {
    215     /* The very first call. Allocate root structure */
    216     if ((pConsole->p_mon_root=(ConEntry_t *)os_MemoryCAlloc(sizeof( ConEntry_t ), 1) ) == NULL)
    217     {
    218         os_error_printf(CU_MSG_ERROR, (PS8)( "ERROR - Console_allocRoot(): cant allocate root\n") );
    219         return;
    220     }
    221     os_strcpy((PS8)pConsole->p_mon_root->name, (PS8)("\\") );
    222     pConsole->p_mon_root->sel = Dir;
    223     pConsole->p_cur_dir = pConsole->p_mon_root;
    224 }
    225 
    226 /* Display current directory */
    227 static VOID Console_displayDir(Console_t* pConsole)
    228 {
    229     S8 out_buf[512];
    230     ConEntry_t *p_token;
    231     ConEntry_t *p_dir = pConsole->p_cur_dir;
    232 
    233     os_sprintf((PS8)out_buf, (PS8)("%s%s> "), (PS8)(p_dir==pConsole->p_mon_root)? (PS8)("") : (PS8)(".../"), (PS8)p_dir->name );
    234     p_token = p_dir->u.dir.first;
    235     while( p_token )
    236     {
    237         if( (os_strlen(out_buf) + os_strlen(p_token->name) + 2)>= sizeof(out_buf) )
    238         {
    239             os_error_printf(CU_MSG_ERROR, ( (PS8)"ERROR - Console_displayDir(): buffer too small....\n") );
    240             break;
    241         }
    242         os_strcat(out_buf, p_token->name );
    243         if ( p_token->sel == Dir )
    244             os_strcat((PS8)out_buf, (PS8)("/" ) );
    245         p_token = p_token->next;
    246         if (p_token)
    247             os_strcat((PS8)out_buf, (PS8)(", ") );
    248     }
    249 
    250     os_error_printf(CU_MSG_INFO2, (PS8)("%s\n"), (PS8)out_buf );
    251 }
    252 
    253 
    254 /*
    255 Cut the first U16 from <p_inbuf>.
    256 Return the U16 in <name> and updated <p_inbuf>
    257 */
    258 static TokenType_t Console_getWord(Console_t* pConsole, PS8 name, U16 len )
    259 {
    260     U16         i=0;
    261     TokenType_t tType;
    262 
    263     pConsole->p_inbuf = Console_ltrim(pConsole->p_inbuf);
    264 
    265     while( *pConsole->p_inbuf && *pConsole->p_inbuf!=' ' && i<len )
    266         name[i++] = *(pConsole->p_inbuf++);
    267 
    268     if (i<len)
    269         name[i] = 0;
    270 
    271     tType   = Console_analizeToken( name );
    272 
    273     return tType;
    274 }
    275 
    276 static TokenType_t Console_getStrParam(Console_t* pConsole, PS8 buf, ConParm_t *param )
    277 {
    278     TokenType_t tType;
    279     U32         i, len = param->hi_val;
    280     PS8         end_buf;
    281 
    282     pConsole->p_inbuf = Console_ltrim(pConsole->p_inbuf);
    283 
    284     if( param->flags & CON_PARM_LINE )
    285     {
    286         os_strcpy(buf, (PS8)pConsole->p_inbuf );
    287         pConsole->p_inbuf += os_strlen(pConsole->p_inbuf);
    288     }
    289     else
    290     {
    291         if( *pConsole->p_inbuf == '\"' )
    292         {
    293             end_buf = os_strchr(pConsole->p_inbuf+1, '\"' );
    294             if( !end_buf )
    295             {
    296                 os_error_printf(CU_MSG_ERROR, (PS8)("ERROR - invalid string param: '%s'\n"), (PS8)pConsole->p_inbuf );
    297                 pConsole->p_inbuf += os_strlen(pConsole->p_inbuf);
    298                 return EmptyToken;
    299             }
    300             if( (end_buf - pConsole->p_inbuf - 1) > (int)len )
    301             {
    302                 os_error_printf(CU_MSG_ERROR, (PS8)("ERROR - param is too long: '%s'\n"), (PS8)pConsole->p_inbuf );
    303                 pConsole->p_inbuf += os_strlen(pConsole->p_inbuf);
    304                 return EmptyToken;
    305             }
    306             *end_buf = 0;
    307             os_strcpy( buf, (PS8)(pConsole->p_inbuf+1 ) );
    308             pConsole->p_inbuf = end_buf + 1;
    309         }
    310         else
    311         {
    312             for( i=0; *pConsole->p_inbuf && *pConsole->p_inbuf!=' ' && i<len; i++ )
    313                 buf[i] = *(pConsole->p_inbuf++);
    314 
    315             buf[i] = 0;
    316             if( *pConsole->p_inbuf && *pConsole->p_inbuf != ' ' )
    317             {
    318                 os_error_printf(CU_MSG_ERROR, (PS8)("ERROR - param is too long: '%s'\n"), (PS8)( pConsole->p_inbuf-os_strlen( buf) ) );
    319                 pConsole->p_inbuf += os_strlen(pConsole->p_inbuf);
    320                 return EmptyToken;
    321             }
    322         }
    323     }
    324 
    325     tType   = Console_analizeToken( buf );
    326 
    327     return tType;
    328 }
    329 
    330 /* Returns number of parameters of the given token
    331 */
    332 static U16 Console_getNParms( ConEntry_t *p_token )
    333 {
    334     U16 i;
    335     if ( !p_token->u.token.parm )
    336         return 0;
    337     for( i=0;
    338          (i<p_token->u.token.totalParams) &&
    339           p_token->u.token.parm[i].name &&
    340           p_token->u.token.parm[i].name[0];
    341          i++ )
    342         ;
    343     return i;
    344 }
    345 
    346 /* Parse p_inbuf string based on parameter descriptions in <p_token>.
    347 Fill parameter values in <p_token>.
    348 Returns the number of parameters filled.
    349 To Do: add a option of one-by-one user input of missing parameters.
    350 */
    351 static S32 Console_parseParms(Console_t* pConsole, ConEntry_t *p_token, U16 *pnParms )
    352 {
    353     U16 nTotalParms = Console_getNParms( p_token );
    354     U16 nParms=0;
    355     PS8 end_buf = NULL;
    356     S8  parm[INBUF_LENGTH];
    357     U16 i, print_params = 0;
    358     U32 val = 0;
    359     S32 sval = 0;
    360 
    361     /* Mark all parameters as don't having an explicit value */
    362     for( i=0; i<nTotalParms; i++ )
    363         p_token->u.token.parm[i].flags |= CON_PARM_NOVAL;
    364 
    365     /*        -----------------              */
    366     pConsole->p_inbuf = Console_ltrim(pConsole->p_inbuf);
    367     if( pConsole->p_inbuf[0] == '!' && pConsole->p_inbuf[1] == '!' )
    368     {
    369         pConsole->p_inbuf += 2; print_params = 1;
    370     }
    371     /*        -----------------              */
    372 
    373     /* Build a format string */
    374     for( i=0; i<nTotalParms; i++ )
    375     {
    376         if (p_token->u.token.parm[i].flags & (CON_PARM_STRING | CON_PARM_LINE) )
    377         {
    378             /* For a string parameter value is the string address */
    379             /* and hi_val is the string length                   */
    380             if (Console_getStrParam(pConsole, parm, &p_token->u.token.parm[i] ) != NameToken)
    381                 break;
    382             if( os_strlen( parm) > p_token->u.token.parm[i].hi_val ||
    383                 (p_token->u.token.parm[i].low_val && p_token->u.token.parm[i].low_val > os_strlen( parm) ) )
    384             {
    385                 os_error_printf(CU_MSG_ERROR, (PS8)("ERROR - param '%s' must be %ld..%ld chars\n"), (PS8)p_token->u.token.parm[i].name,
    386                     (PS8)p_token->u.token.parm[i].low_val, (PS8)p_token->u.token.parm[i].hi_val);
    387                 return FALSE;
    388             }
    389             os_strcpy((PS8)(char *)p_token->u.token.parm[i].value, (PS8)parm);
    390         }
    391         else
    392         {
    393             if (Console_getWord(pConsole, parm, MAX_PARM_LEN ) != NameToken)
    394                 break;
    395 
    396             if (p_token->u.token.parm[i].flags & CON_PARM_SIGN)
    397             {
    398                 sval = os_strtol( parm, &end_buf, 0 );
    399             }
    400             else
    401             {
    402                 val = os_strtoul( parm, &end_buf, 0 );
    403             }
    404             if( end_buf <= parm )
    405                 break;
    406 
    407             /* Check value */
    408             if (p_token->u.token.parm[i].flags & CON_PARM_RANGE)
    409             {
    410                 if (p_token->u.token.parm[i].flags & CON_PARM_SIGN)
    411                 {
    412                     if ((sval < (S32)p_token->u.token.parm[i].low_val) ||
    413                         (sval > (S32)p_token->u.token.parm[i].hi_val) )
    414                     {
    415                         os_error_printf(CU_MSG_ERROR, (PS8)("%s: %d out of range (%d, %d)\n"),
    416                             (PS8)p_token->u.token.parm[i].name, (int)sval,
    417                             (int)p_token->u.token.parm[i].low_val, (int)p_token->u.token.parm[i].hi_val );
    418                         return FALSE;
    419                     }
    420 
    421                 }
    422                 else
    423                 {
    424                     if ((val < p_token->u.token.parm[i].low_val) ||
    425                         (val > p_token->u.token.parm[i].hi_val) )
    426                     {
    427                         os_error_printf(CU_MSG_ERROR , (PS8)("%s: %ld out of range (%ld, %ld)\n"),
    428                             (PS8)p_token->u.token.parm[i].name, (PS8)val,
    429                             (PS8)p_token->u.token.parm[i].low_val, (PS8)p_token->u.token.parm[i].hi_val );
    430                         return FALSE;
    431                     }
    432                 }
    433             }
    434 
    435             if (p_token->u.token.parm[i].flags & CON_PARM_SIGN)
    436                 p_token->u.token.parm[i].value = sval;
    437             else
    438                 p_token->u.token.parm[i].value = val;
    439         }
    440 
    441         p_token->u.token.parm[i].flags &= ~CON_PARM_NOVAL;
    442         ++nParms;
    443     }
    444 
    445     /* Process default values */
    446     for( ; i<nTotalParms; i++ )
    447     {
    448         if ((p_token->u.token.parm[i].flags & CON_PARM_DEFVAL) != 0)
    449         {
    450             p_token->u.token.parm[i].flags &= ~CON_PARM_NOVAL;
    451             ++nParms;
    452         }
    453         else if (!(p_token->u.token.parm[i].flags & CON_PARM_OPTIONAL) )
    454         {
    455             /* Mandatory parameter missing */
    456             return FALSE;
    457         }
    458     }
    459 
    460     if( print_params )
    461     {
    462         os_error_printf((S32)CU_MSG_INFO2, (PS8)("Params: %d\n"), nParms );
    463         for (i=0; i<nParms; i++ )
    464         {
    465             os_error_printf(CU_MSG_INFO2, (PS8)("%d: %s - flags:%d"),
    466                 i+1, (PS8)p_token->u.token.parm[i].name,
    467                 p_token->u.token.parm[i].flags);
    468 
    469             if (p_token->u.token.parm[i].flags & CON_PARM_SIGN)
    470                 os_error_printf(CU_MSG_INFO2, (PS8)("min:%d, max:%d, value:%d "),(PS8)p_token->u.token.parm[i].low_val, (PS8)p_token->u.token.parm[i].hi_val,
    471                 (PS8)p_token->u.token.parm[i].value);
    472             else
    473                 os_error_printf(CU_MSG_INFO2, (PS8)("min:%ld, max:%ld, value:%ld "),(PS8)p_token->u.token.parm[i].low_val, (PS8)p_token->u.token.parm[i].hi_val,
    474                 (PS8)p_token->u.token.parm[i].value);
    475 
    476             os_error_printf(CU_MSG_INFO2, (PS8)("(%#lx)"),(PS8)p_token->u.token.parm[i].value );
    477 
    478             if( p_token->u.token.parm[i].flags & (CON_PARM_LINE | CON_PARM_STRING ))
    479             {
    480                 os_error_printf(CU_MSG_INFO2, (PS8)(" - '%s'"), (PS8)(char *) p_token->u.token.parm[i].value );
    481             }
    482             os_error_printf(CU_MSG_INFO2, (PS8)("\n") );
    483         }
    484 
    485     }
    486     *pnParms = nParms;
    487 
    488     return TRUE;
    489 }
    490 
    491 /* Serach a token by name in the current directory */
    492 static ConEntry_t *Console_searchToken( ConEntry_t *p_dir, PS8 name )
    493 {
    494     ConEntry_t *p_token;
    495     U16        name_len = (U16)os_strlen( name );
    496 
    497     /* Check alias */
    498     p_token = p_dir->u.dir.first;
    499     while( p_token )
    500     {
    501         if (p_token->alias &&
    502             (name_len == ALIAS_LEN) &&
    503             !Console_stricmp( p_token->alias, name, ALIAS_LEN ) )
    504             return p_token;
    505         p_token = p_token->next;
    506     }
    507 
    508     /* Check name */
    509     p_token = p_dir->u.dir.first;
    510     while( p_token )
    511     {
    512         if (!Console_stricmp( p_token->name, name, name_len ) )
    513             break;
    514         p_token = p_token->next;
    515     }
    516 
    517     return p_token;
    518 }
    519 
    520 
    521 /* Display help for each entry in the current directory */
    522 VOID  Console_dirHelp(Console_t* pConsole)
    523 {
    524     ConEntry_t *p_token;
    525     S8        print_str[80];
    526 
    527     p_token = pConsole->p_cur_dir->u.dir.first;
    528 
    529     while( p_token )
    530     {
    531         if (p_token->sel == Dir)
    532             os_sprintf( print_str, (PS8)"%s: directory\n", (PS8)p_token->name );
    533         else
    534             os_sprintf( print_str, (PS8)("%s(%d parms): %s\n"),
    535             (PS8)p_token->name, Console_getNParms(p_token), p_token->help );
    536         os_error_printf(CU_MSG_INFO2,  (PS8)print_str );
    537         p_token = p_token->next;
    538     }
    539 
    540     os_error_printf(CU_MSG_INFO2, (PS8)("Type ? <name> for command help, \"/\"-root, \"..\"-upper\n") );
    541 }
    542 
    543 
    544 /* Display help a token */
    545 static VOID  Console_displayHelp(Console_t* pConsole, ConEntry_t *p_token )
    546 {
    547     S8 bra, ket;
    548     U16 nTotalParms = Console_getNParms( p_token );
    549     U16 i;
    550 
    551 
    552     os_error_printf(CU_MSG_INFO2, (PS8)("%s: %s "), (PS8)p_token->help, (PS8)p_token->name );
    553     for( i=0; i<nTotalParms; i++ )
    554     {
    555         if (p_token->u.token.parm[i].flags & CON_PARM_OPTIONAL)
    556         {
    557             bra = '['; ket=']';
    558         }
    559         else
    560         {
    561             bra = '<'; ket='>';
    562         }
    563         os_error_printf(CU_MSG_INFO2, (PS8)("%c%s"), bra, (PS8)p_token->u.token.parm[i].name );
    564         if (p_token->u.token.parm[i].flags & CON_PARM_DEFVAL)
    565         {
    566             os_error_printf(CU_MSG_INFO2, (PS8)("=%lu"), (PS8)p_token->u.token.parm[i].value);
    567         }
    568         if (p_token->u.token.parm[i].flags & CON_PARM_RANGE)
    569         {
    570             os_error_printf(CU_MSG_INFO2, (PS8)(p_token->u.token.parm[i].flags & CON_PARM_SIGN) ? (PS8)(" (%d..%d%s)") : (PS8)(" (%lu..%lu%s)"),
    571                 (PS8)p_token->u.token.parm[i].low_val,
    572                 (PS8)p_token->u.token.parm[i].hi_val,
    573                 (PS8)(p_token->u.token.parm[i].flags & (CON_PARM_STRING | CON_PARM_LINE)) ? (PS8)(" chars") : (PS8)("") );
    574 
    575         }
    576         os_error_printf(CU_MSG_INFO2, (PS8)("%c \n"),ket );
    577     }
    578 }
    579 
    580 /* Choose unique alias for <name> in <p_dir> */
    581 /* Currently only single-character aliases are supported */
    582 static S32 Console_chooseAlias( ConEntry_t *p_dir, ConEntry_t *p_new_token )
    583 {
    584     ConEntry_t *p_token;
    585     S32         i;
    586     S8          c;
    587     PS8         new_alias = NULL;
    588 
    589     /* find alias given from user */
    590     for(i=0; p_new_token->name[i]; i++ )
    591     {
    592         if( os_isupper( p_new_token->name[i]) )
    593         {
    594             new_alias = &p_new_token->name[i];
    595             break;
    596         }
    597     }
    598 
    599     Console_strlwr( p_new_token->name );
    600 
    601     if( new_alias )
    602     {
    603         p_token = p_dir->u.dir.first;
    604 
    605         while( p_token )
    606         {
    607             if (p_token->alias && (os_tolower(*p_token->alias ) == *new_alias) )
    608             {
    609                 os_error_printf(CU_MSG_ERROR, (PS8)("Error - duplicated alias '%c' in <%s> and <%s>**\n"), *new_alias,
    610                     (PS8)p_token->name, (PS8)p_new_token->name );
    611                 return 0;
    612             }
    613             p_token = p_token->next;
    614         }
    615         *new_alias = (S8)os_toupper(*new_alias);
    616         p_new_token->alias = new_alias;
    617         return 1;
    618     }
    619 
    620     i = 0;
    621     while( p_new_token->name[i] )
    622     {
    623         c = p_new_token->name[i];
    624         p_token = p_dir->u.dir.first;
    625 
    626         while( p_token )
    627         {
    628             if (p_token->alias &&
    629                 (os_tolower(*p_token->alias ) == c) )
    630                 break;
    631             p_token = p_token->next;
    632         }
    633         if (p_token)
    634             ++i;
    635         else
    636         {
    637             p_new_token->name[i] = (S8)os_toupper( c );
    638             p_new_token->alias   = &p_new_token->name[i];
    639             break;
    640         }
    641     }
    642     return 1;
    643 }
    644 
    645 /* Parse the given input string and exit.
    646 All commands in the input string are executed one by one.
    647 */
    648 static U8 Console_ParseString(Console_t* pConsole, PS8 input_string )
    649 {
    650     ConEntry_t  *p_token;
    651     S8          name[MAX_NAME_LEN];
    652     TokenType_t tType;
    653     U16         nParms;
    654 
    655     if (!pConsole->p_mon_root)
    656         return 1;
    657 
    658     if(!pConsole->isDeviceOpen)
    659     {
    660         Console_GetDeviceStatus(pConsole);
    661         if(!pConsole->isDeviceOpen)
    662         {
    663             os_error_printf(CU_MSG_ERROR, (PS8)("ERROR - Console_ParseString - Device isn't loaded !!!\n") );
    664             return 1;
    665         }
    666     }
    667 
    668     if( input_string[os_strlen( input_string)-1] == '\n' )
    669     {
    670         PS8 s = &input_string[os_strlen( input_string)-1];
    671         *s = 0;
    672     }
    673     pConsole->p_inbuf = input_string;
    674     pConsole->stop_UI_Monitor = FALSE;
    675 
    676     /* Interpret empty string as "display directory" */
    677     if ( pConsole->p_inbuf && !*pConsole->p_inbuf )
    678         Console_displayDir(pConsole);
    679 
    680     while(!pConsole->stop_UI_Monitor && pConsole->p_inbuf && *pConsole->p_inbuf)
    681     {
    682         tType = Console_getWord(pConsole, name, MAX_NAME_LEN );
    683         switch( tType )
    684         {
    685 
    686         case NameToken:
    687             p_token = Console_searchToken( pConsole->p_cur_dir, name );
    688             if (p_token == NULL)
    689             {
    690                 os_error_printf(CU_MSG_ERROR, (PS8)("**Error: '%s'**\n"),name);
    691                 pConsole->p_inbuf = NULL;
    692             }
    693             else if (p_token->sel == Dir)
    694             {
    695                 pConsole->p_cur_dir = p_token;
    696                 Console_displayDir(pConsole);
    697             }
    698             else
    699             {  /* Function token */
    700                 if (!Console_parseParms(pConsole, p_token, &nParms ))
    701                 {
    702                     Console_displayHelp(pConsole, p_token );
    703                 }
    704                 else
    705                 {
    706                     p_token->u.token.f_tokenFunc(pConsole->hCuCmd, p_token->u.token.parm, nParms );
    707                 }
    708             }
    709             break;
    710 
    711         case UpToken: /* Go to upper directory */
    712             if (pConsole->p_cur_dir->u.dir.upper)
    713                 pConsole->p_cur_dir = pConsole->p_cur_dir->u.dir.upper;
    714             Console_displayDir(pConsole);
    715             break;
    716 
    717         case RootToken: /* Go to the root directory */
    718             if (pConsole->p_cur_dir->u.dir.upper)
    719                 pConsole->p_cur_dir = pConsole->p_mon_root;
    720             Console_displayDir(pConsole);
    721             break;
    722 
    723         case HelpToken: /* Display help */
    724             if (( Console_getWord(pConsole, name, MAX_NAME_LEN ) == NameToken ) &&
    725                 ((p_token = Console_searchToken( pConsole->p_cur_dir, name )) != NULL ) &&
    726                 (p_token->sel == Token) )
    727                 Console_displayHelp(pConsole, p_token);
    728             else
    729                 Console_dirHelp(pConsole);
    730             break;
    731 
    732         case DirHelpToken:
    733             Console_displayDir(pConsole);
    734             os_error_printf(CU_MSG_INFO2, (PS8)("Type ? <name> for command help, \"/\"-root, \"..\"-upper\n") );
    735             break;
    736 
    737         case BreakToken: /* Clear buffer */
    738             pConsole->p_inbuf = NULL;
    739             break;
    740 
    741         case QuitToken: /* Go to upper directory */
    742 			return 1;
    743 
    744         case EmptyToken:
    745             break;
    746 
    747         }
    748     }
    749 	return 0;
    750 }
    751 
    752 /* functions */
    753 /*************/
    754 
    755 THandle Console_Create(const PS8 device_name, S32 BypassSupplicant, PS8 pSupplIfFile)
    756 {
    757     Console_t* pConsole = (Console_t*)os_MemoryCAlloc(sizeof(Console_t), sizeof(U8));
    758     if(pConsole == NULL)
    759     {
    760         os_error_printf(CU_MSG_ERROR, (PS8)("Error - Console_Create - cant allocate control block\n") );
    761         return NULL;
    762     }
    763 
    764     pConsole->hCuCmd = CuCmd_Create(device_name, pConsole, BypassSupplicant, pSupplIfFile);
    765     if(pConsole->hCuCmd == NULL)
    766     {
    767         Console_Destroy(pConsole);
    768         return NULL;
    769     }
    770 
    771     Console_allocRoot(pConsole);
    772 
    773     pConsole->isDeviceOpen = FALSE;
    774 
    775     return pConsole;
    776 }
    777 
    778 VOID Console_Destroy(THandle hConsole)
    779 {
    780     Console_t* pConsole = (Console_t*)hConsole;
    781 
    782     if(pConsole->hCuCmd)
    783     {
    784         CuCmd_Destroy(pConsole->hCuCmd);
    785     }
    786     if (pConsole->p_mon_root)
    787     {
    788     Console_FreeEntry(pConsole->p_mon_root);
    789     }
    790     os_MemoryFree(pConsole);
    791 }
    792 
    793 VOID Console_Stop(THandle hConsole)
    794 {
    795     ((Console_t*)hConsole)->stop_UI_Monitor = TRUE;
    796 }
    797 
    798 /* Monitor driver */
    799 VOID Console_Start(THandle hConsole)
    800 {
    801     Console_t* pConsole = (Console_t*)hConsole;
    802     S8  inbuf[INBUF_LENGTH];
    803     S32 res;
    804 
    805     if (!pConsole->p_mon_root)
    806         return;
    807 
    808     pConsole->stop_UI_Monitor = FALSE;
    809     Console_displayDir(pConsole);
    810 
    811     while(!pConsole->stop_UI_Monitor)
    812     {
    813         /* get input string */
    814         res = os_getInputString(inbuf, sizeof(inbuf));
    815         if (res == FALSE)
    816         {
    817             if(pConsole->stop_UI_Monitor)
    818             {
    819                 continue;
    820             }
    821             else
    822             {
    823                 return;
    824             }
    825         }
    826 
    827         if(res == OS_GETINPUTSTRING_CONTINUE)
    828             continue;
    829 
    830         /* change to NULL terminated strings */
    831         if( inbuf[os_strlen(inbuf)-1] == '\n' )
    832             inbuf[os_strlen(inbuf)-1] = 0;
    833 
    834         /* parse the string */
    835         Console_ParseString(pConsole, inbuf);
    836     }
    837 
    838 }
    839 
    840 VOID Console_GetDeviceStatus(THandle hConsole)
    841 {
    842     Console_t* pConsole = (Console_t*)hConsole;
    843 
    844     if(OK == CuCmd_GetDeviceStatus(pConsole->hCuCmd))
    845     {
    846         pConsole->isDeviceOpen = TRUE;
    847     }
    848 }
    849 
    850 
    851 /***************************************************************
    852 
    853   Function : consoleAddDirExt
    854 
    855     Description: Add subdirectory
    856 
    857       Parameters: p_root - root directory handle (might be NULL)
    858       name   - directory name
    859 
    860         Output:  the new created directory handle
    861         =NULL - failure
    862 ***************************************************************/
    863 THandle Console_AddDirExt(THandle  hConsole,
    864                           THandle   hRoot,         /* Upper directory handle. NULL=root */
    865                           const PS8  name,          /* New directory name */
    866                           const PS8  desc )         /* Optional dir description */
    867 {
    868     Console_t* pConsole = (Console_t*)hConsole;
    869     ConEntry_t *p_root = (ConEntry_t *)hRoot;
    870     ConEntry_t *p_dir;
    871     ConEntry_t **p_e;
    872 
    873     if (!p_root)
    874         p_root = pConsole->p_mon_root;
    875 
    876     if(!( p_root && (p_root->sel == Dir)))
    877         return NULL;
    878 
    879     if ( (p_dir=(ConEntry_t *)os_MemoryAlloc(sizeof( ConEntry_t )) ) == NULL)
    880         return NULL;
    881 
    882     os_memset( p_dir, 0, sizeof( ConEntry_t ) );
    883     os_strncpy( p_dir->name, name, MAX_NAME_LEN );
    884     os_strncpy( p_dir->help, desc, MAX_HELP_LEN );
    885     p_dir->sel = Dir;
    886 
    887     Console_chooseAlias( p_root, p_dir );
    888 
    889     /* Add new directory to the root's list */
    890     p_dir->u.dir.upper = p_root;
    891     p_e = &(p_root->u.dir.first);
    892     while (*p_e)
    893         p_e = &((*p_e)->next);
    894     *p_e = p_dir;
    895 
    896     return p_dir;
    897 }
    898 
    899 /***************************************************************
    900 
    901   Function : consoleAddToken
    902 
    903     Description: Add token
    904 
    905       Parameters: p_dir  - directory handle (might be NULL=root)
    906       name   - token name
    907       help   - help string
    908       p_func - token handler
    909       p_parms- array of parameter descriptions.
    910       Must be terminated with {0}.
    911       Each parm descriptor is a struct
    912       { "myname",         - name
    913       10,               - low value
    914       20,               - high value
    915       0 }               - default value =-1 no default
    916       or address for string parameter
    917 
    918         Output:  E_OK - OK
    919         !=0 - error
    920 ***************************************************************/
    921 consoleErr Console_AddToken(  THandle hConsole,
    922                                 THandle      hDir,
    923                                 const PS8     name,
    924                                 const PS8     help,
    925                                 FuncToken_t   p_func,
    926                                 ConParm_t     p_parms[] )
    927 {
    928     Console_t* pConsole = (Console_t*)hConsole;
    929     ConEntry_t *p_dir = (ConEntry_t *)hDir;
    930     ConEntry_t *p_token;
    931     ConEntry_t **p_e;
    932     U16       i;
    933 
    934     if (!pConsole->p_mon_root)
    935       Console_allocRoot(pConsole);
    936 
    937     if (!p_dir)
    938       p_dir = pConsole->p_mon_root;
    939 
    940     if(!( p_dir && (p_dir->sel == Dir)))
    941         return E_ERROR;
    942 
    943 
    944     /* Initialize token structure */
    945     if((p_token = (ConEntry_t *)os_MemoryCAlloc(1,sizeof(ConEntry_t))) == NULL)
    946     {
    947      os_error_printf(CU_MSG_ERROR, (PS8)("** no memory **\n") );
    948       return E_NOMEMORY;
    949     }
    950 
    951 
    952     /* Copy name */
    953     os_strncpy( p_token->name, name, MAX_NAME_LEN );
    954     os_strncpy( p_token->help, help, MAX_HELP_LEN );
    955     p_token->sel = Token;
    956     p_token->u.token.f_tokenFunc = p_func;
    957     p_token->u.token.totalParams = 0;
    958 
    959     /* Convert name to lower case and choose alias */
    960     Console_chooseAlias( p_dir, p_token );
    961 
    962     /* Copy parameters */
    963     if ( p_parms )
    964     {
    965        ConParm_t     *p_tmpParms = p_parms;
    966 
    967        /* find the number of params */
    968        while( p_tmpParms->name && p_tmpParms->name[0] )
    969        {
    970             p_token->u.token.totalParams++;
    971             p_tmpParms++;
    972        }
    973        /* allocate the parameters info */
    974        p_token->u.token.parm = (ConParm_t *)os_MemoryAlloc(p_token->u.token.totalParams * sizeof(ConParm_t));
    975        p_token->u.token.name = (PS8*)os_MemoryAlloc(p_token->u.token.totalParams * sizeof(PS8));
    976        if ((p_token->u.token.parm == NULL) || (p_token->u.token.name == NULL))
    977        {
    978             os_error_printf(CU_MSG_ERROR, (PS8)("** no memory for params\n") );
    979             os_MemoryFree(p_token);
    980             return E_NOMEMORY;
    981        }
    982        for (i=0; i < p_token->u.token.totalParams; i++)
    983        {
    984          ConParm_t *p_token_parm = &p_token->u.token.parm[i];
    985 
    986          /* String parameter must have an address */
    987          if(p_parms->flags & (CON_PARM_STRING | CON_PARM_LINE))
    988          {
    989             if ( p_parms->hi_val >= INBUF_LENGTH )
    990             {
    991                os_error_printf(CU_MSG_ERROR, (PS8)("** buffer too big: %s/%s\n"), p_dir->name, name);
    992                 os_MemoryFree(p_token->u.token.parm);
    993                 os_MemoryFree(p_token->u.token.name);
    994                 os_MemoryFree(p_token);
    995                 return E_NOMEMORY;
    996 
    997             }
    998             if (p_parms->hi_val == 0 || (p_parms->flags & CON_PARM_RANGE) )
    999             {
   1000                os_error_printf(CU_MSG_ERROR, (PS8)("** Bad string param definition: %s/%s\n"), p_dir->name, name );
   1001                 os_MemoryFree(p_token->u.token.parm);
   1002                 os_MemoryFree(p_token->u.token.name);
   1003                 os_MemoryFree(p_token);
   1004                 return E_BADPARM;
   1005             }
   1006             p_parms->value = (U32)os_MemoryCAlloc(1,p_parms->hi_val+1);
   1007             if( !p_parms->value )
   1008             {
   1009                 os_error_printf(CU_MSG_ERROR, (PS8)("** No memory: %s/%s (max.size=%ld)\n"), p_dir->name, name, p_parms->hi_val );
   1010                 os_MemoryFree(p_token->u.token.parm);
   1011                 os_MemoryFree(p_token->u.token.name);
   1012                 os_MemoryFree(p_token);
   1013                 return E_NOMEMORY;
   1014             }
   1015         }
   1016 
   1017         /* Copy parameter */
   1018         *p_token_parm = *p_parms;
   1019         if( p_token_parm->hi_val || p_token_parm->low_val )
   1020             p_token_parm->flags |= CON_PARM_RANGE;
   1021 
   1022         p_token->u.token.name[i] = os_MemoryAlloc(os_strlen(p_parms->name));
   1023         if (p_token->u.token.name[i] == NULL)
   1024         {
   1025             os_error_printf(CU_MSG_ERROR, (PS8)("** Error allocate param name\n"));
   1026             os_MemoryFree(p_token->u.token.parm);
   1027             os_MemoryFree(p_token->u.token.name);
   1028             os_MemoryFree(p_token);
   1029             return E_NOMEMORY;
   1030         }
   1031          p_token_parm->name = (PS8)p_token->u.token.name[i];
   1032          os_strncpy( p_token->u.token.name[i], p_parms->name, os_strlen(p_parms->name) );
   1033          ++p_parms;
   1034       } /*end of for loop*/
   1035     }
   1036 
   1037     /* Add token to the directory */
   1038     p_e = &(p_dir->u.dir.first);
   1039     while (*p_e)
   1040       p_e = &((*p_e)->next);
   1041     *p_e = p_token;
   1042 
   1043     return E_OK;
   1044 }
   1045 
   1046 int consoleRunScript( char *script_file, THandle hConsole)
   1047 {
   1048     FILE *hfile = fopen(script_file, "r" );
   1049 	U8 status = 0;
   1050     Console_t* pConsole = (Console_t*)hConsole;
   1051 
   1052     if( hfile )
   1053     {
   1054         char buf[INBUF_LENGTH];
   1055         pConsole->stop_UI_Monitor = FALSE;
   1056 
   1057         while( fgets(buf, sizeof(buf), hfile ) )
   1058         {
   1059             status = Console_ParseString(pConsole, buf);
   1060 			if (status == 1)
   1061 				return TRUE;
   1062 			if( pConsole->stop_UI_Monitor )
   1063                 break;
   1064         }
   1065 
   1066         fclose(hfile);
   1067     }
   1068     else
   1069 	{
   1070 		os_error_printf(CU_MSG_ERROR, (PS8)("ERROR in script: %s \n"), (PS8)script_file);
   1071 	}
   1072     return pConsole->stop_UI_Monitor;
   1073 }
   1074