##############################################################################
#                                                                            #
# IAR ARM ANSI C/C++ Compiler V4.11A/W32               20/Jul/2004  18:58:51 #
# Copyright 1999-2004 IAR Systems. All rights reserved.                      #
#                                                                            #
#    Cpu mode        =  arm                                                  #
#    Endian          =  little                                               #
#    Stack alignment =  4                                                    #
#    Source file     =  C:\medusa\clichar.c                                  #
#    Command line    =  -I "C:\Program Files\IAR Systems\Embedded Workbench  #
#                       4.0\ARM\INC\" -lc C:\medusa\Debug\List\ -la          #
#                       C:\medusa\Debug\List\ -o C:\medusa\Debug\Obj\ -s2    #
#                       --no_cse --no_unroll --no_inline --no_code_motion    #
#                       --no_tbaa --no_clustering --no_scheduling --debug    #
#                       --cpu_mode arm --endian little --cpu ARM7TDMI-S      #
#                       --stack_align 4 -e --fpu None                        #
#                       "-D_DLIB_CONFIG_FILE=C:\Program Files\IAR            #
#                       Systems\Embedded Workbench                           #
#                       4.0\ARM\LIB\dl4tpannl8n.h" C:\medusa\clichar.c       #
#    List file       =  C:\medusa\Debug\List\clichar.lst                     #
#    Object file     =  C:\medusa\Debug\Obj\clichar.r79                      #
#                                                                            #
#                                                                            #
##############################################################################

C:\medusa\clichar.c
      1          #include "archinc.h"
      2          #include "cli.h"
      3          #include "clichar.h"
      4          #include "uart0.h"
      5          #include "eventq.h"
      6          
      7          #include <stdio.h>
      8          
      9          /*
     10           * This module handles low-level character buffering and terminal 
     11           * operations like backspace. It forwards completed commands to the 
     12           * higher level parser for further processing. 
     13           * 
     14           * For quick reference, here's a list of common special characters and their
     15           * escape sequences/hex values for C:
     16           *
     17           * Embed Character   Dec  Hex  Oct 
     18           * ----- ----------- --- ---- ----
     19           *  \b   backspace     8 \x08 \010
     20           *  \f   form feed    12 \x0C \014
     21           *  \n   newline      10 \x0A \012
     22           *  \r   car. return  13 \x0D \015
     23           *  \t   horiz. tab    9 \x09 \011
     24           *  \u   denotes hex 117 \x75 \165
     25           *  \v   vertical tab 11 \x0B \013
     26           *  \x   denotes hex 120 \x78 \170
     27           *  \"   "            34 \x22 \042
     28           *  \'   '            39 \x27 \047
     29           *  \\   \            92 \x5C \134
     30           */
     31           
     32          static char prompt[] = {'\r','\n','-','>',' ','\0'};
     33          
     34          static char inputBuf[CONFIG_CLICHAR_INPUT_BUF_SIZE];
     35          static int currentBufIndex = 0;
     36          
     37          static char outputBuf[CONFIG_CLICHAR_OUTPUT_BUF_SIZE];
     38          
     39          static char * pCurrentBuffer;
     40          
     41          static boolean echoChars;
     42          
     43          static void handleEvent(void);
     44          
     45          /*
     46           * yes, these are overkill, but when we get a real RTOS, we can buffer
     47           *  multiple commands while processing one
     48           */
     49          
     50          static char * getBuffer(void)
     51          {
     52            currentBufIndex = 0;
     53            return (char *)&(inputBuf[currentBufIndex]);
     54          }
     55          
     56          static void returnBuffer(void)
     57          {
     58            return;
     59          }
     60          
     61          char * clicharGetOutputBuffer(int * pBufLen)
     62          {
     63            if (pBufLen != NULL) {
     64              *pBufLen = CONFIG_CLICHAR_OUTPUT_BUF_SIZE;
     65              }
     66          
     67            return (char *)outputBuf;
     68          }
     69          
     70          static void outputString(const char * pStr, int len)
     71          {
     72            int i = 0;
     73          
     74            if ((*pStr == '\0') || (len <= 0))
     75              return;
     76          
     77            while((*pStr != '\x00') && (i < len)) {
     78              if (CLISEND(*pStr) == 0) {
     79                pStr++; i++;
     80                }
     81              }
     82          }
     83          
     84          // TODO: this is ugly, fix it
     85          void clicharPuts(char * pStr)
     86          {
     87            outputString(pStr, 255);
     88          }
     89          
     90          void clicharSendOutputBuffer(char * pBuffer, int bufLen)
     91          {
     92            int i;
     93            char * pCh;
     94          
     95            if (pBuffer == NULL) {
     96              pBuffer = (char *)(&outputBuf[0]);
     97              bufLen = CONFIG_CLICHAR_OUTPUT_BUF_SIZE;
     98              }
     99          
    100            pCh = &(pBuffer[0]); i = 0;
    101          
    102            while((*pCh != '\0') && (i<bufLen)) {
    103              if (CLISEND(*pCh) == 0) {
    104                pCh++; i++;
    105                }
    106              }
    107          }
    108          
    109          
    110          static void putPrompt(void)
    111          {
    112            clicharSendOutputBuffer(prompt, SIZEOF_ARRAY(prompt));
                                                   ^
Warning[Pe191]: type qualifier is meaningless on cast type
    113          }
    114          
    115          static int accumulateCmd(char inCh)
    116          {
    117            int retVal = -1;
    118            
    119            if (inCh <= 0) {
    120              return retVal;
    121              }
    122          
    123            switch (inCh) {
    124              case 0x03:
    125                // Control-C
    126                if (echoChars == true) {
    127                  CLISEND('^');
    128                  CLISEND('C');
    129                  }
    130                // invalidate the entire line
    131                currentBufIndex = 0;
    132                putPrompt();
    133                break;
    134              case '\b':
    135                // handle backspace
    136                if (currentBufIndex == 0) {
    137                  // at beginning of line: just bark at user
    138                  // this should never be negative since we're circInc'ing
    139                  if (echoChars == true) {
    140                    CLISEND('\a');
    141                    }
    142                  }
    143                else {
    144          	// clear the char by backing up, writing a space, backing up again
    145                  if (echoChars == true) {
    146                    CLISEND('\b'); CLISEND(' '); CLISEND('\b');
    147                    }
    148                  circDec(currentBufIndex, 0, (CONFIG_CLICHAR_INPUT_BUF_SIZE-1));
    149                  }
    150                break;
    151              case '\r':
    152              case '\n':
    153                // handle newline: null-term and submit command for processing
    154                pCurrentBuffer[currentBufIndex] = '\0';
    155                if (echoChars == true) {
    156                  CLISEND('\r');
    157                  CLISEND('\n');
    158                  }
    159                retVal = 0;
    160                break;
    161              default:
    162                if (echoChars == true) {
    163                  CLISEND(inCh);
    164                  }
    165                pCurrentBuffer[currentBufIndex] = inCh;
    166                /*
    167                 * do the circInc so if the console just stuffs random characters 
    168                 * with no line delimeter down our throat, we'll keep wrapping 
    169                 * around and not scribble all over memory
    170                 */
    171                circInc(currentBufIndex, 0, (CONFIG_CLICHAR_INPUT_BUF_SIZE-1));
    172                break;
    173              } // switch()
    174              
    175            return retVal;
    176          }
    177          
    178          // for testing...
    179          void clicharEventTrigger(void)
    180          {
    181            handleEvent();
    182          }
    183          
    184          static void handleEvent(void)
    185          {
    186            char ch;
    187            int retVal;
                       ^
Warning[Pe550]: variable "retVal" was set but never used
    188            
    189            /*
    190             * we start with a buffer, so we should always have one at this point
    191             */
    192          
    193            while((retVal = CLIGET(ch)) != -1) {
    194              if ((retVal = accumulateCmd(ch)) != -1) {
    195                cliDoCommand(pCurrentBuffer, CONFIG_CLICHAR_INPUT_BUF_SIZE);
    196                returnBuffer();
    197                pCurrentBuffer = getBuffer();
    198                putPrompt();
    199                }
    200             }
    201          }
    202          
    203          int echoHandler(int argc, char * argv[], int flags)
    204          {
    205            int retVal = -1;
    206            int bufLen;
    207            char * pOutBuf;
    208          
    209            if (argc != 2)
    210              return -1;
    211          
    212            pOutBuf = clicharGetOutputBuffer(&bufLen);
    213          
    214            switch(*argv[1]) {
    215              case 'n':
    216              case 'N':
    217              case '0':
    218                echoChars = false;
    219                sprintf(pOutBuf, "%s: echo is off\r\n",argv[0]);
    220                retVal = 0;
    221                break;
    222              case 'y':
    223              case 'Y':
    224              case '1':
    225                echoChars = true;
    226                sprintf(pOutBuf, "%s: echo is on\r\n",argv[0]);
    227                retVal = 0;
    228                break;
    229              }
    230          
    231            if (retVal == 0) {
    232              clicharSendOutputBuffer(pOutBuf, bufLen);
    233              }
    234          
    235            return retVal;
    236          }
    237          
    238          int clicharInit(void)
    239          {
    240            char * pCh;
    241            int i;
    242          
    243            // echo characters to start
    244            echoChars = true;
    245          
    246            // get a buffer and clear it
    247            pCurrentBuffer = getBuffer();
    248            for(pCh=pCurrentBuffer, i=0;i<CONFIG_CLICHAR_INPUT_BUF_SIZE;i++, pCh++)
    249              pCh = '\0';
    250          
    251            // connect us to the console
    252            eventqRegisterHandler(CONSOLE_RXCHAR, handleEvent);
    253          
    254            // lastly, tell the user we're ready...
    255            putPrompt();
    256          
    257            cliRegisterCommand("echo", echoHandler, "echo [{0 | n(o) | N(o)} {1 | y(es) | Y(es)}]");
    258          
    259            return 0;
    260          }

   Maximum stack usage in bytes:

     Function                CSTACK
     --------                ------
     accumulateCmd              12
     clicharEventTrigger         4
     clicharGetOutputBuffer      0
     clicharInit                12
     clicharPuts                 8
     clicharSendOutputBuffer    20
     echoHandler                28
     getBuffer                   0
     handleEvent                12
     outputString               16
     putPrompt                   4
     returnBuffer                0


   Segment part sizes:

     Function/Label                 Bytes
     --------------                 -----
     prompt                            6
     inputBuf                        256
     currentBufIndex                   4
     outputBuf                       256
     pCurrentBuffer                    4
     echoChars                         4
     getBuffer                        36
     returnBuffer                      4
     clicharGetOutputBuffer           28
     outputString                     92
     clicharPuts                      24
     clicharSendOutputBuffer         100
     putPrompt                        24
     accumulateCmd                   464
     clicharEventTrigger              12
     handleEvent                      96
     echoHandler                     284
     clicharInit                     132
     ??DataTable3                      4
     ??DataTable24                     4
     ??DataTable29                     4
     ??DataTable31                     4
     ?<Initializer for prompt>         6
     ?<Constant "%s: echo is off\r\n">
                                      20
     ?<Constant "%s: echo is on\r\n">
                                      20
     ?<Constant "echo">                8
     ?<Constant "echo [{0 | n(o) | N(o...">
                                      48
      Others                          96

 
 1 384 bytes in segment CODE
    96 bytes in segment DATA_C
     6 bytes in segment DATA_I
     6 bytes in segment DATA_ID
   524 bytes in segment DATA_Z
    24 bytes in segment INITTAB
 
 1 312 bytes of CODE  memory (+ 96 bytes shared)
   102 bytes of CONST memory
   530 bytes of DATA  memory

Errors: none
Warnings: 2
