SLRE(Super Light Regular Expression library) Unit Test Code.

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
monpetit
Date:
Thu Jul 28 08:10:30 2016 +0000
Commit message:
initial commit: unit tests are passed.

Changed in this revision

RTT/SEGGER_RTT.c Show annotated file Show diff for this revision Revisions of this file
RTT/SEGGER_RTT.h Show annotated file Show diff for this revision Revisions of this file
RTT/SEGGER_RTT_Conf.h Show annotated file Show diff for this revision Revisions of this file
RTT/retarget_io.c Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
slre/slre.c Show annotated file Show diff for this revision Revisions of this file
slre/slre.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RTT/SEGGER_RTT.c	Thu Jul 28 08:10:30 2016 +0000
@@ -0,0 +1,1329 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2016  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: support@segger.com               *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       SEGGER RTT * Real Time Transfer for embedded targets         *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+* All rights reserved.                                               *
+*                                                                    *
+* * This software may in its unmodified form be freely redistributed *
+*   in source form.                                                  *
+* * The source code may be modified, provided the source code        *
+*   retains the above copyright notice, this list of conditions and  *
+*   the following disclaimer.                                        *
+* * Modified versions of this software in source or linkable form    *
+*   may not be distributed without prior consent of SEGGER.          *
+* * This software may only be used for communication with SEGGER     *
+*   J-Link debug probes.                                             *
+*                                                                    *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
+* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
+* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
+* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
+* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
+* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
+* DAMAGE.                                                            *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       RTT version: 5.12g                                           *
+*                                                                    *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File    : SEGGER_RTT.c
+Purpose : Implementation of SEGGER real-time transfer (RTT) which
+          allows real-time communication on targets which support
+          debugger memory accesses while the CPU is running.
+
+Additional information:
+          Type "int" is assumed to be 32-bits in size
+          H->T    Host to target communication
+          T->H    Target to host communication
+
+          RTT channel 0 is always present and reserved for Terminal usage.
+          Name is fixed to "Terminal"
+
+          Effective buffer size: SizeOfBuffer - 1
+
+          WrOff == RdOff:       Buffer is empty
+          WrOff == (RdOff - 1): Buffer is full
+          WrOff >  RdOff:       Free space includes wrap-around
+          WrOff <  RdOff:       Used space includes wrap-around
+          (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0):  
+                                Buffer full and wrap-around after next byte
+
+
+----------------------------------------------------------------------
+*/
+
+#include "SEGGER_RTT.h"
+
+#include <string.h>                 // for memcpy
+
+/*********************************************************************
+*
+*       Configuration, default values
+*
+**********************************************************************
+*/
+
+#ifndef   BUFFER_SIZE_UP
+  #define BUFFER_SIZE_UP                                  1024  // Size of the buffer for terminal output of target, up to host
+#endif
+
+#ifndef   BUFFER_SIZE_DOWN
+  #define BUFFER_SIZE_DOWN                                16    // Size of the buffer for terminal input to target from host (Usually keyboard input)
+#endif
+
+#ifndef   SEGGER_RTT_MAX_NUM_UP_BUFFERS
+  #define SEGGER_RTT_MAX_NUM_UP_BUFFERS                    2    // Number of up-buffers (T->H) available on this target
+#endif
+
+#ifndef   SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
+  #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS                  2    // Number of down-buffers (H->T) available on this target
+#endif
+
+#ifndef SEGGER_RTT_BUFFER_SECTION
+  #if defined SEGGER_RTT_SECTION
+    #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION
+  #endif
+#endif
+
+#ifndef   SEGGER_RTT_MODE_DEFAULT
+  #define SEGGER_RTT_MODE_DEFAULT                         SEGGER_RTT_MODE_NO_BLOCK_SKIP
+#endif
+
+#ifndef   SEGGER_RTT_LOCK
+  #define SEGGER_RTT_LOCK()
+#endif
+
+#ifndef   SEGGER_RTT_UNLOCK
+  #define SEGGER_RTT_UNLOCK()
+#endif
+
+#ifndef   STRLEN
+  #define STRLEN(a)                                       strlen((a))
+#endif
+
+#ifndef   MEMCPY
+  #define MEMCPY(pDest, pSrc, NumBytes)                   memcpy((pDest), (pSrc), (NumBytes))
+#endif
+
+#ifndef   MIN
+  #define MIN(a, b)         (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef   MAX
+  #define MAX(a, b)         (((a) > (b)) ? (a) : (b))
+#endif
+//
+// For some environments, NULL may not be defined until certain headers are included
+//
+#ifndef NULL
+  #define NULL 0
+#endif
+
+/*********************************************************************
+*
+*       Static const data
+*
+**********************************************************************
+*/
+
+static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+/*********************************************************************
+*
+*       Static data
+*
+**********************************************************************
+*/
+//
+// RTT Control Block and allocate buffers for channel 0
+//
+#ifdef SEGGER_RTT_SECTION
+  #if (defined __GNUC__)
+    __attribute__ ((section (SEGGER_RTT_SECTION))) SEGGER_RTT_CB _SEGGER_RTT;
+  #elif (defined __ICCARM__) || (defined __ICCRX__)
+    #pragma location=SEGGER_RTT_SECTION
+    SEGGER_RTT_CB _SEGGER_RTT;
+  #elif (defined __CC_ARM__)
+    __attribute__ ((section (SEGGER_RTT_SECTION), zero_init)) SEGGER_RTT_CB _SEGGER_RTT;
+  #else
+    SEGGER_RTT_CB _SEGGER_RTT;
+  #endif
+#else
+    SEGGER_RTT_CB _SEGGER_RTT;
+#endif
+
+#ifdef SEGGER_RTT_BUFFER_SECTION
+  #if (defined __GNUC__)
+    __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acUpBuffer  [BUFFER_SIZE_UP];
+    __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acDownBuffer[BUFFER_SIZE_DOWN];
+  #elif (defined __ICCARM__) || (defined __ICCRX__)
+    #pragma location=SEGGER_RTT_BUFFER_SECTION
+    static char _acUpBuffer  [BUFFER_SIZE_UP];
+    #pragma location=SEGGER_RTT_BUFFER_SECTION
+    static char _acDownBuffer[BUFFER_SIZE_DOWN];
+  #elif (defined __CC_ARM__)
+    __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acUpBuffer  [BUFFER_SIZE_UP];
+    __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acDownBuffer[BUFFER_SIZE_DOWN];
+  #else
+    static char _acUpBuffer  [BUFFER_SIZE_UP];
+    static char _acDownBuffer[BUFFER_SIZE_DOWN];
+  #endif
+#else
+    static char _acUpBuffer  [BUFFER_SIZE_UP];
+    static char _acDownBuffer[BUFFER_SIZE_DOWN];
+#endif
+
+static char _ActiveTerminal;
+
+/*********************************************************************
+*
+*       Static functions
+*
+**********************************************************************
+*/
+
+/*********************************************************************
+*
+*       _DoInit()
+*
+*  Function description
+*    Initializes the control block an buffers.
+*    May only be called via INIT() to avoid overriding settings.
+*
+*/
+#define INIT()  do {                                            \
+                  if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); }  \
+                } while (0)
+static void _DoInit(void) {
+  SEGGER_RTT_CB* p;
+  //
+  // Initialize control block
+  //
+  p = &_SEGGER_RTT;
+  p->MaxNumUpBuffers    = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
+  p->MaxNumDownBuffers  = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
+  //
+  // Initialize up buffer 0
+  //
+  p->aUp[0].sName         = "Terminal";
+  p->aUp[0].pBuffer       = _acUpBuffer;
+  p->aUp[0].SizeOfBuffer  = sizeof(_acUpBuffer);
+  p->aUp[0].RdOff         = 0u;
+  p->aUp[0].WrOff         = 0u;
+  p->aUp[0].Flags         = SEGGER_RTT_MODE_DEFAULT;
+  //
+  // Initialize down buffer 0
+  //
+  p->aDown[0].sName         = "Terminal";
+  p->aDown[0].pBuffer       = _acDownBuffer;
+  p->aDown[0].SizeOfBuffer  = sizeof(_acDownBuffer);
+  p->aDown[0].RdOff         = 0u;
+  p->aDown[0].WrOff         = 0u;
+  p->aDown[0].Flags         = SEGGER_RTT_MODE_DEFAULT;
+  //
+  // Finish initialization of the control block.
+  // Copy Id string in three steps to make sure "SEGGER RTT" is not found
+  // in initializer memory (usually flash) by J-Link
+  //
+  strcpy(&p->acID[7], "RTT");
+  strcpy(&p->acID[0], "SEGGER");
+  p->acID[6] = ' ';
+}
+
+/*********************************************************************
+*
+*       _WriteBlocking()
+*
+*  Function description
+*    Stores a specified number of characters in SEGGER RTT ring buffer
+*    and updates the associated write pointer which is periodically
+*    read by the host.
+*    The caller is responsible for managing the write chunk sizes as
+*    _WriteBlocking() will block until all data has been posted successfully.
+*
+*  Parameters
+*    pRing        Ring buffer to post to.
+*    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
+*    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
+*
+*  Return value
+*    >= 0 - Number of bytes written into buffer.
+*/
+static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) {
+  unsigned NumBytesToWrite;
+  unsigned NumBytesWritten;
+  unsigned RdOff;
+  unsigned WrOff;
+  //
+  // Write data to buffer and handle wrap-around if necessary
+  //
+  NumBytesWritten = 0u;
+  WrOff = pRing->WrOff;
+  do {
+    RdOff = pRing->RdOff;                         // May be changed by host (debug probe) in the meantime
+    if (RdOff > WrOff) {
+      NumBytesToWrite = RdOff - WrOff - 1u;
+    } else {
+      NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u);
+    }
+    NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff));      // Number of bytes that can be written until buffer wrap-around
+    NumBytesToWrite = MIN(NumBytesToWrite, NumBytes);
+    memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite);
+    NumBytesWritten += NumBytesToWrite;
+    pBuffer         += NumBytesToWrite;
+    NumBytes        -= NumBytesToWrite;
+    WrOff           += NumBytesToWrite;
+    if (WrOff == pRing->SizeOfBuffer) {
+      WrOff = 0u;
+    }
+    pRing->WrOff = WrOff;
+  } while (NumBytes);
+  //
+  return NumBytesWritten;
+}
+
+/*********************************************************************
+*
+*       _WriteNoCheck()
+*
+*  Function description
+*    Stores a specified number of characters in SEGGER RTT ring buffer
+*    and updates the associated write pointer which is periodically
+*    read by the host.
+*    It is callers responsibility to make sure data actually fits in buffer.
+*
+*  Parameters
+*    pRing        Ring buffer to post to.
+*    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
+*    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
+*
+*  Notes
+*    (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking
+*/
+static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) {
+  unsigned NumBytesAtOnce;
+  unsigned WrOff;
+  unsigned Rem;
+
+  WrOff = pRing->WrOff;
+  Rem = pRing->SizeOfBuffer - WrOff;
+  if (Rem > NumBytes) {
+    //
+    // All data fits before wrap around
+    //
+    memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
+    pRing->WrOff = WrOff + NumBytes;
+  } else {
+    //
+    // We reach the end of the buffer, so need to wrap around
+    //
+    NumBytesAtOnce = Rem;
+    memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce);
+    NumBytesAtOnce = NumBytes - Rem;
+    memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce);
+    pRing->WrOff = NumBytesAtOnce;
+  }
+}
+
+/*********************************************************************
+*
+*       _PostTerminalSwitch()
+*
+*  Function description
+*    Switch terminal to the given terminal ID.  It is the caller's
+*    responsibility to ensure the terminal ID is correct and there is
+*    enough space in the buffer for this to complete successfully.
+*
+*  Parameters
+*    pRing        Ring buffer to post to.
+*    TerminalId   Terminal ID to switch to.
+*/
+static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) {
+  char ac[2];
+
+  ac[0] = 0xFFu;
+  ac[1] = _aTerminalId[TerminalId];  // Caller made already sure that TerminalId does not exceed our terminal limit
+  _WriteBlocking(pRing, ac, 2u);
+}
+
+/*********************************************************************
+*
+*       _GetAvailWriteSpace()
+*
+*  Function description
+*    Returns the number of bytes that can be written to the ring
+*    buffer without blocking.
+*
+*  Parameters
+*    pRing        Ring buffer to check.
+*
+*  Return value
+*    Number of bytes that are free in the buffer.
+*/
+static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) {
+  unsigned RdOff;
+  unsigned WrOff;
+  unsigned r;
+  //
+  // Avoid warnings regarding volatile access order.  It's not a problem
+  // in this case, but dampen compiler enthusiasm.
+  //
+  RdOff = pRing->RdOff;
+  WrOff = pRing->WrOff;
+  if (RdOff <= WrOff) {
+    r = pRing->SizeOfBuffer - 1u - WrOff + RdOff;
+  } else {
+    r = RdOff - WrOff - 1u;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       Public code
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*       SEGGER_RTT_ReadNoLock()
+*
+*  Function description
+*    Reads characters from SEGGER real-time-terminal control block
+*    which have been previously stored by the host.
+*    Do not lock against interrupts and multiple access.
+*
+*  Parameters
+*    BufferIndex  Index of Down-buffer to be used (e.g. 0 for "Terminal").
+*    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
+*    BufferSize   Size of the target application buffer.
+*
+*  Return value
+*    Number of bytes that have been read.
+*/
+unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
+  unsigned                NumBytesRem;
+  unsigned                NumBytesRead;
+  unsigned                RdOff;
+  unsigned                WrOff;
+  unsigned char*          pBuffer;
+  SEGGER_RTT_BUFFER_DOWN* pRing;
+  //
+  INIT();
+  pRing = &_SEGGER_RTT.aDown[BufferIndex];
+  pBuffer = (unsigned char*)pData;
+  RdOff = pRing->RdOff;
+  WrOff = pRing->WrOff;
+  NumBytesRead = 0u;
+  //
+  // Read from current read position to wrap-around of buffer, first
+  //
+  if (RdOff > WrOff) {
+    NumBytesRem = pRing->SizeOfBuffer - RdOff;
+    NumBytesRem = MIN(NumBytesRem, BufferSize);
+    memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
+    NumBytesRead += NumBytesRem;
+    pBuffer      += NumBytesRem;
+    BufferSize   -= NumBytesRem;
+    RdOff        += NumBytesRem;
+    //
+    // Handle wrap-around of buffer
+    //
+    if (RdOff == pRing->SizeOfBuffer) {
+      RdOff = 0u;
+    }
+  }
+  //
+  // Read remaining items of buffer
+  //
+  NumBytesRem = WrOff - RdOff;
+  NumBytesRem = MIN(NumBytesRem, BufferSize);
+  if (NumBytesRem > 0u) {
+    memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
+    NumBytesRead += NumBytesRem;
+    pBuffer      += NumBytesRem;
+    BufferSize   -= NumBytesRem;
+    RdOff        += NumBytesRem;
+  }
+  if (NumBytesRead) {
+    pRing->RdOff = RdOff;
+  }
+  //
+  return NumBytesRead;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_Read
+*
+*  Function description
+*    Reads characters from SEGGER real-time-terminal control block
+*    which have been previously stored by the host.
+*
+*  Parameters
+*    BufferIndex  Index of Down-buffer to be used (e.g. 0 for "Terminal").
+*    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
+*    BufferSize   Size of the target application buffer.
+*
+*  Return value
+*    Number of bytes that have been read.
+*/
+unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) {
+  unsigned NumBytesRead;
+  //
+  SEGGER_RTT_LOCK();
+  //
+  // Call the non-locking read function
+  //
+  NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize);
+  //
+  // Finish up.
+  //
+  SEGGER_RTT_UNLOCK();
+  //
+  return NumBytesRead;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_WriteWithOverwriteNoLock
+*
+*  Function description
+*    Stores a specified number of characters in SEGGER RTT
+*    control block.
+*    SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application 
+*    and overwrites data if the data does not fit into the buffer.
+*
+*  Parameters
+*    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+*    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
+*    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
+*
+*  Notes
+*    (1) If there is not enough space in the "Up"-buffer, data is overwritten.
+*    (2) For performance reasons this function does not call Init()
+*        and may only be called after RTT has been initialized.
+*        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
+*    (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link 
+*        connection reads RTT data.
+*/
+void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+  const char*           pData;
+  SEGGER_RTT_BUFFER_UP* pRing;
+  unsigned              Avail;
+
+  pData = (const char *)pBuffer;
+  //
+  // Get "to-host" ring buffer and copy some elements into local variables.
+  //
+  pRing = &_SEGGER_RTT.aUp[BufferIndex];
+  //
+  // Check if we will overwrite data and need to adjust the RdOff.
+  //
+  if (pRing->WrOff == pRing->RdOff) {
+    Avail = pRing->SizeOfBuffer - 1u;
+  } else if ( pRing->WrOff < pRing->RdOff) {
+    Avail = pRing->RdOff - pRing->WrOff - 1u;
+  } else {
+    Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer;
+  }
+  if (NumBytes > Avail) {
+    pRing->RdOff += (NumBytes - Avail);
+    while (pRing->RdOff >= pRing->SizeOfBuffer) {
+      pRing->RdOff -= pRing->SizeOfBuffer;
+    }
+  }
+  //
+  // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds
+  //
+  Avail = pRing->SizeOfBuffer - pRing->WrOff;
+  do {
+    if (Avail > NumBytes) {
+      //
+      // Last round
+      //
+#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead.
+      char* pDst;
+      pDst = pRing->pBuffer + pRing->WrOff;
+      pRing->WrOff += NumBytes;
+      do {
+        *pDst++ = *pData++;
+      } while (--NumBytes);
+#else
+      memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
+      pRing->WrOff += NumBytes;
+#endif
+      break;  //Alternatively: NumBytes = 0;
+    } else {
+      //
+      //  Wrap-around necessary, write until wrap-around and reset WrOff
+      //
+      memcpy(pRing->pBuffer + pRing->WrOff, pData, Avail);
+      pData += Avail;
+      pRing->WrOff = 0;
+      NumBytes -= Avail;
+      Avail = (pRing->SizeOfBuffer - 1);
+    }
+  } while (NumBytes);
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_WriteSkipNoLock
+*
+*  Function description
+*    Stores a specified number of characters in SEGGER RTT
+*    control block which is then read by the host.
+*    SEGGER_RTT_WriteSkipNoLock does not lock the application and
+*    skips all data, if the data does not fit into the buffer.
+*
+*  Parameters
+*    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+*    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
+*    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
+*
+*  Return value
+*    Number of bytes which have been stored in the "Up"-buffer.
+*
+*  Notes
+*    (1) If there is not enough space in the "Up"-buffer, all data is dropped.
+*    (2) For performance reasons this function does not call Init()
+*        and may only be called after RTT has been initialized.
+*        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
+*/
+unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+  const char*           pData;
+  SEGGER_RTT_BUFFER_UP* pRing;
+  unsigned              Avail;
+  unsigned              RdOff;
+  unsigned              WrOff;
+  unsigned              Rem;
+
+  pData = (const char *)pBuffer;
+  //
+  // Get "to-host" ring buffer and copy some elements into local variables.
+  //
+  pRing = &_SEGGER_RTT.aUp[BufferIndex];
+  RdOff = pRing->RdOff;
+  WrOff = pRing->WrOff;
+  //
+  // Handle the most common cases fastest.
+  // Which is:
+  //    RdOff <= WrOff -> Space until wrap around is free.
+  //  AND
+  //    WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary.
+  //
+  //  OR
+  //
+  //    RdOff > WrOff -> Space until RdOff - 1 is free.
+  //  AND
+  //    WrOff + NumBytes < RdOff -> Data fits into buffer
+  //
+  if (RdOff <= WrOff) {
+    //
+    // Get space until WrOff will be at wrap around.
+    //
+    Avail = pRing->SizeOfBuffer - 1u - WrOff ;
+    if (Avail >= NumBytes) {
+#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead.
+      char* pDst;
+      pDst = pRing->pBuffer + WrOff;
+      WrOff += NumBytes;
+      do {
+        *pDst++ = *pData++;
+      } while (--NumBytes);
+      pRing->WrOff = WrOff + NumBytes;
+#else
+      memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
+      pRing->WrOff = WrOff + NumBytes;
+#endif
+      return 1;
+    }
+    //
+    // If data did not fit into space until wrap around calculate complete space in buffer.
+    //
+    Avail += RdOff;
+    //
+    // If there is still no space for the whole of this output, don't bother.
+    //
+    if (Avail >= NumBytes) {
+      //
+      //  OK, we have enough space in buffer. Copy in one or 2 chunks
+      //
+      Rem = pRing->SizeOfBuffer - WrOff;      // Space until end of buffer
+      if (Rem > NumBytes) {
+        memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
+        pRing->WrOff = WrOff + NumBytes;
+      } else {
+        //
+        // We reach the end of the buffer, so need to wrap around
+        //
+        memcpy(pRing->pBuffer + WrOff, pData, Rem);
+        memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem);
+        pRing->WrOff = NumBytes - Rem;
+      }
+      return 1;
+    }
+  } else {
+    Avail = RdOff - WrOff - 1u;
+    if (Avail >= NumBytes) {
+      memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
+      pRing->WrOff = WrOff + NumBytes;
+      return 1;
+    }
+  }
+  //
+  // If we reach this point no data has been written
+  //
+  return 0;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_WriteNoLock
+*
+*  Function description
+*    Stores a specified number of characters in SEGGER RTT
+*    control block which is then read by the host.
+*    SEGGER_RTT_WriteNoLock does not lock the application.
+*
+*  Parameters
+*    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+*    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
+*    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
+*
+*  Return value
+*    Number of bytes which have been stored in the "Up"-buffer.
+*
+*  Notes
+*    (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped.
+*    (2) For performance reasons this function does not call Init()
+*        and may only be called after RTT has been initialized.
+*        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
+*/
+unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+  unsigned              Status;
+  unsigned              Avail;
+  const char*           pData;
+  SEGGER_RTT_BUFFER_UP* pRing;
+
+  pData = (const char *)pBuffer;
+  //
+  // Get "to-host" ring buffer.
+  //
+  pRing = &_SEGGER_RTT.aUp[BufferIndex];
+  //
+  // How we output depends upon the mode...
+  //
+  switch (pRing->Flags) {
+  case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
+    //
+    // If we are in skip mode and there is no space for the whole
+    // of this output, don't bother.
+    //
+    Avail = _GetAvailWriteSpace(pRing);
+    if (Avail < NumBytes) {
+      Status = 0u;
+    } else {
+      Status = NumBytes;
+      _WriteNoCheck(pRing, pData, NumBytes);
+    }
+    break;
+  case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
+    //
+    // If we are in trim mode, trim to what we can output without blocking.
+    //
+    Avail = _GetAvailWriteSpace(pRing);
+    Status = Avail < NumBytes ? Avail : NumBytes;
+    _WriteNoCheck(pRing, pData, Status);
+    break;
+  case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
+    //
+    // If we are in blocking mode, output everything.
+    //
+    Status = _WriteBlocking(pRing, pData, NumBytes);
+    break;
+  default:
+    Status = 0u;
+    break;
+  }
+  //
+  // Finish up.
+  //
+  return Status;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_Write
+*
+*  Function description
+*    Stores a specified number of characters in SEGGER RTT
+*    control block which is then read by the host.
+*
+*  Parameters
+*    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+*    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
+*    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
+*
+*  Return value
+*    Number of bytes which have been stored in the "Up"-buffer.
+*
+*  Notes
+*    (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped.
+*/
+unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+  unsigned Status;
+  //
+  INIT();
+  SEGGER_RTT_LOCK();
+  //
+  // Call the non-locking write function
+  //
+  Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes);
+  //
+  // Finish up.
+  //
+  SEGGER_RTT_UNLOCK();
+  //
+  return Status;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_WriteString
+*
+*  Function description
+*    Stores string in SEGGER RTT control block.
+*    This data is read by the host.
+*
+*  Parameters
+*    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+*    s            Pointer to string.
+*
+*  Return value
+*    Number of bytes which have been stored in the "Up"-buffer.
+*
+*  Notes
+*    (1) If there is not enough space in the "Up"-buffer, depending on configuration,
+*        remaining characters may be dropped or RTT module waits until there is more space in the buffer.
+*    (2) String passed to this function has to be \0 terminated
+*    (3) \0 termination character is *not* stored in RTT buffer
+*/
+unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) {
+  unsigned Len;
+
+  Len = STRLEN(s);
+  return SEGGER_RTT_Write(BufferIndex, s, Len);
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_GetKey
+*
+*  Function description
+*    Reads one character from the SEGGER RTT buffer.
+*    Host has previously stored data there.
+*
+*  Return value
+*    <  0 -   No character available (buffer empty).
+*    >= 0 -   Character which has been read. (Possible values: 0 - 255)
+*
+*  Notes
+*    (1) This function is only specified for accesses to RTT buffer 0.
+*/
+int SEGGER_RTT_GetKey(void) {
+  char c;
+  int r;
+
+  r = (int)SEGGER_RTT_Read(0u, &c, 1u);
+  if (r == 1) {
+    r = (int)(unsigned char)c;
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_WaitKey
+*
+*  Function description
+*    Waits until at least one character is avaible in the SEGGER RTT buffer.
+*    Once a character is available, it is read and this function returns.
+*
+*  Return value
+*    >=0 -   Character which has been read.
+*
+*  Notes
+*    (1) This function is only specified for accesses to RTT buffer 0
+*    (2) This function is blocking if no character is present in RTT buffer
+*/
+int SEGGER_RTT_WaitKey(void) {
+  int r;
+
+  do {
+    r = SEGGER_RTT_GetKey();
+  } while (r < 0);
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_HasKey
+*
+*  Function description
+*    Checks if at least one character for reading is available in the SEGGER RTT buffer.
+*
+*  Return value
+*    == 0 -     No characters are available to read.
+*    == 1 -     At least one character is available.
+*
+*  Notes
+*    (1) This function is only specified for accesses to RTT buffer 0
+*/
+int SEGGER_RTT_HasKey(void) {
+  unsigned RdOff;
+  int r;
+
+  INIT();
+  RdOff = _SEGGER_RTT.aDown[0].RdOff;
+  if (RdOff != _SEGGER_RTT.aDown[0].WrOff) {
+    r = 1;
+  } else {
+    r = 0;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_HasData
+*
+*  Function description
+*    Check if there is data from the host in the given buffer.
+*
+*  Return value:
+*  ==0:  No data
+*  !=0:  Data in buffer
+*
+*/
+unsigned SEGGER_RTT_HasData(unsigned BufferIndex) {
+  SEGGER_RTT_BUFFER_DOWN* pRing;
+  unsigned                v;
+
+  pRing = &_SEGGER_RTT.aDown[BufferIndex];
+  v = pRing->WrOff;
+  return v - pRing->RdOff;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_AllocDownBuffer
+*
+*  Function description
+*    Run-time configuration of the next down-buffer (H->T).
+*    The next buffer, which is not used yet is configured.
+*    This includes: Buffer address, size, name, flags, ...
+*
+*  Parameters
+*    sName        Pointer to a constant name string.
+*    pBuffer      Pointer to a buffer to be used.
+*    BufferSize   Size of the buffer.
+*    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
+*
+*  Return value
+*    >= 0 - O.K. Buffer Index
+*     < 0 - Error
+*/
+int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
+  int BufferIndex;
+
+  INIT();
+  SEGGER_RTT_LOCK();
+  BufferIndex = 0;
+  do {
+    if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) {
+      break;
+    }
+    BufferIndex++;
+  } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers);
+  if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) {
+    _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
+    _SEGGER_RTT.aDown[BufferIndex].pBuffer      = (char*)pBuffer;
+    _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
+    _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
+    _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
+    _SEGGER_RTT.aDown[BufferIndex].Flags        = Flags;
+  } else {
+    BufferIndex = -1;
+  }
+  SEGGER_RTT_UNLOCK();
+  return BufferIndex;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_AllocUpBuffer
+*
+*  Function description
+*    Run-time configuration of the next up-buffer (T->H).
+*    The next buffer, which is not used yet is configured.
+*    This includes: Buffer address, size, name, flags, ...
+*
+*  Parameters
+*    sName        Pointer to a constant name string.
+*    pBuffer      Pointer to a buffer to be used.
+*    BufferSize   Size of the buffer.
+*    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
+*
+*  Return value
+*    >= 0 - O.K. Buffer Index
+*     < 0 - Error
+*/
+int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
+  int BufferIndex;
+
+  INIT();
+  SEGGER_RTT_LOCK();
+  BufferIndex = 0;
+  do {
+    if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) {
+      break;
+    }
+    BufferIndex++;
+  } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers);
+  if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) {
+    _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
+    _SEGGER_RTT.aUp[BufferIndex].pBuffer      = (char*)pBuffer;
+    _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
+    _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
+    _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
+    _SEGGER_RTT.aUp[BufferIndex].Flags        = Flags;
+  } else {
+    BufferIndex = -1;
+  }
+  SEGGER_RTT_UNLOCK();
+  return BufferIndex;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_ConfigUpBuffer
+*
+*  Function description
+*    Run-time configuration of a specific up-buffer (T->H).
+*    Buffer to be configured is specified by index.
+*    This includes: Buffer address, size, name, flags, ...
+*
+*  Parameters
+*    BufferIndex  Index of the buffer to configure.
+*    sName        Pointer to a constant name string.
+*    pBuffer      Pointer to a buffer to be used.
+*    BufferSize   Size of the buffer.
+*    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
+*
+*  Return value
+*    >= 0 - O.K.
+*     < 0 - Error
+*/
+int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
+  int r;
+
+  INIT();
+  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
+    SEGGER_RTT_LOCK();
+    if (BufferIndex > 0u) {
+      _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
+      _SEGGER_RTT.aUp[BufferIndex].pBuffer      = (char*)pBuffer;
+      _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
+      _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
+      _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
+    }
+    _SEGGER_RTT.aUp[BufferIndex].Flags          = Flags;
+    SEGGER_RTT_UNLOCK();
+    r =  0;
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_ConfigDownBuffer
+*
+*  Function description
+*    Run-time configuration of a specific down-buffer (H->T).
+*    Buffer to be configured is specified by index.
+*    This includes: Buffer address, size, name, flags, ...
+*
+*  Parameters
+*    BufferIndex  Index of the buffer to configure.
+*    sName        Pointer to a constant name string.
+*    pBuffer      Pointer to a buffer to be used.
+*    BufferSize   Size of the buffer.
+*    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
+*
+*  Return value
+*    >= 0  O.K.
+*     < 0  Error
+*/
+int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
+  int r;
+
+  INIT();
+  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
+    SEGGER_RTT_LOCK();
+    if (BufferIndex > 0u) {
+      _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
+      _SEGGER_RTT.aDown[BufferIndex].pBuffer      = (char*)pBuffer;
+      _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
+      _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
+      _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
+    }
+    _SEGGER_RTT.aDown[BufferIndex].Flags          = Flags;
+    SEGGER_RTT_UNLOCK();
+    r =  0;
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_SetNameUpBuffer
+*
+*  Function description
+*    Run-time configuration of a specific up-buffer name (T->H).
+*    Buffer to be configured is specified by index.
+*
+*  Parameters
+*    BufferIndex  Index of the buffer to renamed.
+*    sName        Pointer to a constant name string.
+*
+*  Return value
+*    >= 0  O.K.
+*     < 0  Error
+*/
+int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) {
+  int r;
+
+  INIT();
+  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
+    SEGGER_RTT_LOCK();
+    _SEGGER_RTT.aUp[BufferIndex].sName = sName;
+    SEGGER_RTT_UNLOCK();
+    r =  0;
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_SetNameDownBuffer
+*
+*  Function description
+*    Run-time configuration of a specific Down-buffer name (T->H).
+*    Buffer to be configured is specified by index.
+*
+*  Parameters
+*    BufferIndex  Index of the buffer to renamed.
+*    sName        Pointer to a constant name string.
+*
+*  Return value
+*    >= 0  O.K.
+*     < 0  Error
+*/
+int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
+  int r;
+
+  INIT();
+  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
+    SEGGER_RTT_LOCK();
+    _SEGGER_RTT.aDown[BufferIndex].sName = sName;
+    SEGGER_RTT_UNLOCK();
+    r =  0;
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_Init
+*
+*  Function description
+*    Initializes the RTT Control Block.
+*    Should be used in RAM targets, at start of the application.
+*
+*/
+void SEGGER_RTT_Init (void) {
+  _DoInit();
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_SetTerminal
+*
+*  Function description
+*    Sets the terminal to be used for output on channel 0.
+*
+*  Parameters
+*    TerminalId  Index of the terminal.
+*
+*  Return value
+*    >= 0  O.K.
+*     < 0  Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id)
+*/
+int SEGGER_RTT_SetTerminal (char TerminalId) {
+  char                  ac[2];
+  SEGGER_RTT_BUFFER_UP* pRing;
+  unsigned Avail;
+  int r;
+  //
+  INIT();
+  //
+  r = 0;
+  ac[0] = 0xFFU;
+  if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels
+    ac[1] = _aTerminalId[(unsigned char)TerminalId];
+    pRing = &_SEGGER_RTT.aUp[0];    // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
+    SEGGER_RTT_LOCK();    // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing
+    if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
+      _ActiveTerminal = TerminalId;
+      _WriteBlocking(pRing, ac, 2u);
+    } else {                                                                            // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
+      Avail = _GetAvailWriteSpace(pRing);
+      if (Avail >= 2) {
+        _ActiveTerminal = TerminalId;    // Only change active terminal in case of success
+        _WriteNoCheck(pRing, ac, 2u);
+      } else {
+        r = -1;
+      }
+    }
+    SEGGER_RTT_UNLOCK();
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_TerminalOut
+*
+*  Function description
+*    Writes a string to the given terminal
+*     without changing the terminal for channel 0.
+*
+*  Parameters
+*    TerminalId   Index of the terminal.
+*    s            String to be printed on the terminal.
+*
+*  Return value
+*    >= 0 - Number of bytes written.
+*     < 0 - Error.
+*
+*/
+int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) {
+  int                   Status;
+  unsigned              FragLen;
+  unsigned              Avail;
+  SEGGER_RTT_BUFFER_UP* pRing;
+  //
+  INIT();
+  //
+  // Validate terminal ID.
+  //
+  if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels
+    //
+    // Get "to-host" ring buffer.
+    //
+    pRing = &_SEGGER_RTT.aUp[0];
+    //
+    // Need to be able to change terminal, write data, change back.
+    // Compute the fixed and variable sizes.
+    //
+    FragLen = strlen(s);
+    //
+    // How we output depends upon the mode...
+    //
+    SEGGER_RTT_LOCK();
+    Avail = _GetAvailWriteSpace(pRing);
+    switch (pRing->Flags & SEGGER_RTT_MODE_MASK) {
+    case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
+      //
+      // If we are in skip mode and there is no space for the whole
+      // of this output, don't bother switching terminals at all.
+      //
+      if (Avail < (FragLen + 4u)) {
+        Status = 0;
+      } else {
+        _PostTerminalSwitch(pRing, TerminalId);
+        Status = (int)_WriteBlocking(pRing, s, FragLen);
+        _PostTerminalSwitch(pRing, _ActiveTerminal);
+      }
+      break;
+    case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
+      //
+      // If we are in trim mode and there is not enough space for everything,
+      // trim the output but always include the terminal switch.  If no room
+      // for terminal switch, skip that totally.
+      //
+      if (Avail < 4u) {
+        Status = -1;
+      } else {
+        _PostTerminalSwitch(pRing, TerminalId);
+        Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
+        _PostTerminalSwitch(pRing, _ActiveTerminal);
+      }
+      break;
+    case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
+      //
+      // If we are in blocking mode, output everything.
+      //
+      _PostTerminalSwitch(pRing, TerminalId);
+      Status = (int)_WriteBlocking(pRing, s, FragLen);
+      _PostTerminalSwitch(pRing, _ActiveTerminal);
+      break;
+    default:
+      Status = -1;
+      break;
+    }
+    //
+    // Finish up.
+    //
+    SEGGER_RTT_UNLOCK();
+  } else {
+    Status = -1;
+  }
+  return Status;
+}
+
+
+/*************************** End of file ****************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RTT/SEGGER_RTT.h	Thu Jul 28 08:10:30 2016 +0000
@@ -0,0 +1,234 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2016  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: support@segger.com               *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       SEGGER RTT * Real Time Transfer for embedded targets         *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+* All rights reserved.                                               *
+*                                                                    *
+* * This software may in its unmodified form be freely redistributed *
+*   in source form.                                                  *
+* * The source code may be modified, provided the source code        *
+*   retains the above copyright notice, this list of conditions and  *
+*   the following disclaimer.                                        *
+* * Modified versions of this software in source or linkable form    *
+*   may not be distributed without prior consent of SEGGER.          *
+* * This software may only be used for communication with SEGGER     *
+*   J-Link debug probes.                                             *
+*                                                                    *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
+* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
+* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
+* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
+* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
+* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
+* DAMAGE.                                                            *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       RTT version: 5.12g                                           *
+*                                                                    *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File    : SEGGER_RTT.h
+Purpose : Implementation of SEGGER real-time transfer which allows
+          real-time communication on targets which support debugger 
+          memory accesses while the CPU is running.
+----------------------------------------------------------------------
+*/
+
+#ifndef SEGGER_RTT_H
+#define SEGGER_RTT_H
+
+#include "SEGGER_RTT_Conf.h"
+
+/*********************************************************************
+*
+*       Defines, fixed
+*
+**********************************************************************
+*/
+
+/*********************************************************************
+*
+*       Types
+*
+**********************************************************************
+*/
+
+//
+// Description for a circular buffer (also called "ring buffer")
+// which is used as up-buffer (T->H)
+//
+typedef struct {
+  const     char*    sName;         // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
+            char*    pBuffer;       // Pointer to start of buffer
+            unsigned SizeOfBuffer;  // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
+            unsigned WrOff;         // Position of next item to be written by either target.
+  volatile  unsigned RdOff;         // Position of next item to be read by host. Must be volatile since it may be modified by host.
+            unsigned Flags;         // Contains configuration flags
+} SEGGER_RTT_BUFFER_UP;
+
+//
+// Description for a circular buffer (also called "ring buffer")
+// which is used as down-buffer (H->T)
+//
+typedef struct {
+  const     char*    sName;         // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
+            char*    pBuffer;       // Pointer to start of buffer
+            unsigned SizeOfBuffer;  // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
+  volatile  unsigned WrOff;         // Position of next item to be written by host. Must be volatile since it may be modified by host.
+            unsigned RdOff;         // Position of next item to be read by target (down-buffer).
+            unsigned Flags;         // Contains configuration flags
+} SEGGER_RTT_BUFFER_DOWN;
+
+//
+// RTT control block which describes the number of buffers available
+// as well as the configuration for each buffer
+//
+//
+typedef struct {
+  char                    acID[16];                                 // Initialized to "SEGGER RTT"
+  int                     MaxNumUpBuffers;                          // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2)
+  int                     MaxNumDownBuffers;                        // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2)
+  SEGGER_RTT_BUFFER_UP    aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS];       // Up buffers, transferring information up from target via debug probe to host
+  SEGGER_RTT_BUFFER_DOWN  aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS];   // Down buffers, transferring information down from host via debug probe to target
+} SEGGER_RTT_CB;
+
+/*********************************************************************
+*
+*       Global data
+*
+**********************************************************************
+*/
+extern SEGGER_RTT_CB _SEGGER_RTT;
+
+/*********************************************************************
+*
+*       RTT API functions
+*
+**********************************************************************
+*/
+#ifdef __cplusplus
+  extern "C" {
+#endif
+int          SEGGER_RTT_AllocDownBuffer  (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
+int          SEGGER_RTT_AllocUpBuffer    (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
+int          SEGGER_RTT_ConfigUpBuffer   (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
+int          SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
+int          SEGGER_RTT_GetKey           (void);
+unsigned     SEGGER_RTT_HasData          (unsigned BufferIndex);
+int          SEGGER_RTT_HasKey           (void);
+void         SEGGER_RTT_Init             (void);
+unsigned     SEGGER_RTT_Read             (unsigned BufferIndex,       void* pBuffer, unsigned BufferSize);
+unsigned     SEGGER_RTT_ReadNoLock       (unsigned BufferIndex,       void* pData,   unsigned BufferSize);
+int          SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName);
+int          SEGGER_RTT_SetNameUpBuffer  (unsigned BufferIndex, const char* sName);
+int          SEGGER_RTT_WaitKey          (void);
+unsigned     SEGGER_RTT_Write            (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+unsigned     SEGGER_RTT_WriteNoLock      (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+unsigned     SEGGER_RTT_WriteSkipNoLock  (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+unsigned     SEGGER_RTT_WriteString      (unsigned BufferIndex, const char* s);
+void         SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+//
+// Function macro for performance optimization
+//
+#define      SEGGER_RTT_HASDATA(n)       (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff)
+
+/*********************************************************************
+*
+*       RTT "Terminal" API functions
+*
+**********************************************************************
+*/
+int     SEGGER_RTT_SetTerminal        (char TerminalId);
+int     SEGGER_RTT_TerminalOut        (char TerminalId, const char* s);
+
+/*********************************************************************
+*
+*       RTT printf functions (require SEGGER_RTT_printf.c)
+*
+**********************************************************************
+*/
+int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...);
+#ifdef __cplusplus
+  }
+#endif
+
+/*********************************************************************
+*
+*       Defines
+*
+**********************************************************************
+*/
+
+//
+// Operating modes. Define behavior if buffer is full (not enough space for entire message)
+//
+#define SEGGER_RTT_MODE_NO_BLOCK_SKIP         (0U)     // Skip. Do not block, output nothing. (Default)
+#define SEGGER_RTT_MODE_NO_BLOCK_TRIM         (1U)     // Trim: Do not block, output as much as fits.
+#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL    (2U)     // Block: Wait until there is space in the buffer.
+#define SEGGER_RTT_MODE_MASK                  (3U)
+
+//
+// Control sequences, based on ANSI.
+// Can be used to control color, and clear the screen
+//
+#define RTT_CTRL_RESET                ""         // Reset to default colors
+#define RTT_CTRL_CLEAR                ""         // Clear screen, reposition cursor to top left
+
+#define RTT_CTRL_TEXT_BLACK           ""
+#define RTT_CTRL_TEXT_RED             ""
+#define RTT_CTRL_TEXT_GREEN           ""
+#define RTT_CTRL_TEXT_YELLOW          ""
+#define RTT_CTRL_TEXT_BLUE            ""
+#define RTT_CTRL_TEXT_MAGENTA         ""
+#define RTT_CTRL_TEXT_CYAN            ""
+#define RTT_CTRL_TEXT_WHITE           ""
+
+#define RTT_CTRL_TEXT_BRIGHT_BLACK    ""
+#define RTT_CTRL_TEXT_BRIGHT_RED      ""
+#define RTT_CTRL_TEXT_BRIGHT_GREEN    ""
+#define RTT_CTRL_TEXT_BRIGHT_YELLOW   ""
+#define RTT_CTRL_TEXT_BRIGHT_BLUE     ""
+#define RTT_CTRL_TEXT_BRIGHT_MAGENTA  ""
+#define RTT_CTRL_TEXT_BRIGHT_CYAN     ""
+#define RTT_CTRL_TEXT_BRIGHT_WHITE    ""
+
+#define RTT_CTRL_BG_BLACK             ""
+#define RTT_CTRL_BG_RED               ""
+#define RTT_CTRL_BG_GREEN             ""
+#define RTT_CTRL_BG_YELLOW            ""
+#define RTT_CTRL_BG_BLUE              ""
+#define RTT_CTRL_BG_MAGENTA           ""
+#define RTT_CTRL_BG_CYAN              ""
+#define RTT_CTRL_BG_WHITE             ""
+
+#define RTT_CTRL_BG_BRIGHT_BLACK      ""
+#define RTT_CTRL_BG_BRIGHT_RED        ""
+#define RTT_CTRL_BG_BRIGHT_GREEN      ""
+#define RTT_CTRL_BG_BRIGHT_YELLOW     ""
+#define RTT_CTRL_BG_BRIGHT_BLUE       ""
+#define RTT_CTRL_BG_BRIGHT_MAGENTA    ""
+#define RTT_CTRL_BG_BRIGHT_CYAN       ""
+#define RTT_CTRL_BG_BRIGHT_WHITE      ""
+
+
+#endif
+
+/*************************** End of file ****************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RTT/SEGGER_RTT_Conf.h	Thu Jul 28 08:10:30 2016 +0000
@@ -0,0 +1,242 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2016  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: support@segger.com               *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       SEGGER RTT * Real Time Transfer for embedded targets         *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+* All rights reserved.                                               *
+*                                                                    *
+* * This software may in its unmodified form be freely redistributed *
+*   in source form.                                                  *
+* * The source code may be modified, provided the source code        *
+*   retains the above copyright notice, this list of conditions and  *
+*   the following disclaimer.                                        *
+* * Modified versions of this software in source or linkable form    *
+*   may not be distributed without prior consent of SEGGER.          *
+* * This software may only be used for communication with SEGGER     *
+*   J-Link debug probes.                                             *
+*                                                                    *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
+* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
+* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
+* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
+* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
+* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
+* DAMAGE.                                                            *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       RTT version: 5.12g                                           *
+*                                                                    *
+**********************************************************************
+----------------------------------------------------------------------
+File    : SEGGER_RTT_Conf.h
+Purpose : Implementation of SEGGER real-time transfer (RTT) which 
+          allows real-time communication on targets which support 
+          debugger memory accesses while the CPU is running.
+---------------------------END-OF-HEADER------------------------------
+*/
+
+#ifndef SEGGER_RTT_CONF_H
+#define SEGGER_RTT_CONF_H
+
+#ifdef __ICCARM__
+  #include <intrinsics.h>
+#endif
+
+/*********************************************************************
+*
+*       Defines, configurable
+*
+**********************************************************************
+*/
+
+#define SEGGER_RTT_MAX_NUM_UP_BUFFERS             (2)     // Max. number of up-buffers (T->H) available on this target    (Default: 2)
+#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS           (2)     // Max. number of down-buffers (H->T) available on this target  (Default: 2)
+
+#define BUFFER_SIZE_UP                            (1024)  // Size of the buffer for terminal output of target, up to host (Default: 1k)
+#define BUFFER_SIZE_DOWN                          (16)    // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16)
+
+#define SEGGER_RTT_PRINTF_BUFFER_SIZE             (64u)    // Size of buffer for RTT printf to bulk-send chars via RTT     (Default: 64)
+
+#define SEGGER_RTT_MODE_DEFAULT                   SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0)
+
+//
+// Target is not allowed to perform other RTT operations while string still has not been stored completely.
+// Otherwise we would probably end up with a mixed string in the buffer.
+// If using  RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here.
+// 
+// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4.
+// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches.
+// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly.
+// (Higher priority = lower priority number)
+// Default value for embOS: 128u
+// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+// In case of doubt mask all interrupts: 0u
+// 
+
+#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY         (0x20)   // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20)
+
+/*********************************************************************
+*
+*       RTT lock configuration for SEGGER Embedded Studio, 
+*       Rowley CrossStudio and GCC
+*/
+#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || ((defined __GNUC__) && !defined(__CC_ARM))
+  #ifdef __ARM_ARCH_6M__
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                    unsigned int LockState;                                         \
+                                  __asm volatile ("mrs   %0, primask  \n\t"                         \
+                                                  "mov   r1, $1     \n\t"                           \
+                                                  "msr   primask, r1  \n\t"                         \
+                                                  : "=r" (LockState)                                \
+                                                  :                                                 \
+                                                  : "r1"                                            \
+                                                  );                            
+    
+    #define SEGGER_RTT_UNLOCK()   __asm volatile ("msr   primask, %0  \n\t"                         \
+                                                  :                                                 \
+                                                  : "r" (LockState)                                 \
+                                                  :                                                 \
+                                                  );                                                \
+                                }                                             
+                                  
+  #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__))
+    #ifndef   SEGGER_RTT_MAX_INTERRUPT_PRIORITY
+      #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY   (0x20)
+    #endif
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                    unsigned int LockState;                                         \
+                                  __asm volatile ("mrs   %0, basepri  \n\t"                         \
+                                                  "mov   r1, %1       \n\t"                         \
+                                                  "msr   basepri, r1  \n\t"                         \
+                                                  : "=r" (LockState)                                \
+                                                  : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY)          \
+                                                  : "r1"                                            \
+                                                  );                            
+    
+    #define SEGGER_RTT_UNLOCK()   __asm volatile ("msr   basepri, %0  \n\t"                         \
+                                                  :                                                 \
+                                                  : "r" (LockState)                                 \
+                                                  :                                                 \
+                                                  );                                                \
+                                }
+  
+  #elif defined(__ARM_ARCH_7A__)
+    #define SEGGER_RTT_LOCK() {                                                \
+                                 unsigned int LockState;                       \
+                                 __asm volatile ("mrs r1, CPSR \n\t"           \
+                                                 "mov %0, r1 \n\t"             \
+                                                 "orr r1, r1, #0xC0 \n\t"      \
+                                                 "msr CPSR_c, r1 \n\t"         \
+                                                 : "=r" (LockState)            \
+                                                 :                             \
+                                                 : "r1"                        \
+                                                 );
+
+    #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t"              \
+                                                "mrs r1, CPSR \n\t"            \
+                                                "bic r1, r1, #0xC0 \n\t"       \
+                                                "and r0, r0, #0xC0 \n\t"       \
+                                                "orr r1, r1, r0 \n\t"          \
+                                                "msr CPSR_c, r1 \n\t"          \
+                                                :                              \
+                                                : "r" (LockState)              \
+                                                : "r0", "r1"                   \
+                                                );                             \
+                            }
+#else
+    #define SEGGER_RTT_LOCK()  
+    #define SEGGER_RTT_UNLOCK()
+  #endif
+#endif
+
+/*********************************************************************
+*
+*       RTT lock configuration for IAR EWARM
+*/
+#ifdef __ICCARM__
+  #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__))
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                  unsigned int LockState;                                           \
+                                  LockState = __get_PRIMASK();                                      \
+                                  __set_PRIMASK(1);                           
+                                    
+    #define SEGGER_RTT_UNLOCK()   __set_PRIMASK(LockState);                                         \
+                                }
+  #elif ((defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || (defined (__ARM7M__) && (__CORE__ == __ARM7M__)))
+    #ifndef   SEGGER_RTT_MAX_INTERRUPT_PRIORITY
+      #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY   (0x20)
+    #endif
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                  unsigned int LockState;                                           \
+                                  LockState = __get_BASEPRI();                                      \
+                                  __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);                           
+                                    
+    #define SEGGER_RTT_UNLOCK()   __set_BASEPRI(LockState);                                         \
+                                }  
+  #endif
+#endif
+
+/*********************************************************************
+*
+*       RTT lock configuration for KEIL ARM
+*/
+#ifdef __CC_ARM
+  #if (defined __TARGET_ARCH_6S_M)
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                  unsigned int LockState;                                           \
+                                  register unsigned char PRIMASK __asm( "primask");                 \
+                                  LockState = PRIMASK;                                              \
+                                  PRIMASK = 1u;                                                     \
+                                  __schedule_barrier();
+
+    #define SEGGER_RTT_UNLOCK()   PRIMASK = LockState;                                              \
+                                  __schedule_barrier();                                             \
+                                }
+  #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M))
+    #ifndef   SEGGER_RTT_MAX_INTERRUPT_PRIORITY
+      #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY   (0x20)
+    #endif
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                  unsigned int LockState;                                           \
+                                  register unsigned char BASEPRI __asm( "basepri");                 \
+                                  LockState = BASEPRI;                                              \
+                                  BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY;                      \
+                                  __schedule_barrier();
+
+    #define SEGGER_RTT_UNLOCK()   BASEPRI = LockState;                                              \
+                                  __schedule_barrier();                                             \
+                                }
+  #endif
+#endif
+
+/*********************************************************************
+*
+*       RTT lock configuration fallback
+*/
+#ifndef   SEGGER_RTT_LOCK
+  #define SEGGER_RTT_LOCK()                // Lock RTT (nestable)   (i.e. disable interrupts)
+#endif
+
+#ifndef   SEGGER_RTT_UNLOCK
+  #define SEGGER_RTT_UNLOCK()              // Unlock RTT (nestable) (i.e. enable previous interrupt lock state)
+#endif
+
+#endif
+/*************************** End of file ****************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RTT/retarget_io.c	Thu Jul 28 08:10:30 2016 +0000
@@ -0,0 +1,759 @@
+/*-----------------------------------------------------------------------------
+ * Name:    retarget_io.c
+ * Purpose: Retarget I/O
+ * Rev.:    1.1.0
+ *-----------------------------------------------------------------------------*/
+ 
+/* Copyright (c) 2013 - 2015 ARM LIMITED
+ 
+   All rights reserved.
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   - Neither the name of ARM nor the names of its contributors may be used
+     to endorse or promote products derived from this software without
+     specific prior written permission.
+   *
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
+   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+   ---------------------------------------------------------------------------*/
+ 
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <rt_sys.h>
+ 
+// #include "RTE_Components.h"
+#define RTE_Compiler_IO_STDOUT          /* Compiler I/O: STDOUT */
+#define RTE_Compiler_IO_STDOUT_User     /* Compiler I/O: STDOUT User */
+#include "SEGGER_RTT.h"
+ 
+#ifdef RTE_Compiler_IO_File_FS
+#include "rl_fs_lib.h"
+#endif
+ 
+ 
+#ifndef STDIN_ECHO
+#define STDIN_ECHO      0       /* STDIN: echo to STDOUT */
+#endif
+#ifndef STDOUT_CR_LF
+#define STDOUT_CR_LF    0       /* STDOUT: add CR for LF */
+#endif
+#ifndef STDERR_CR_LF
+#define STDERR_CR_LF    0       /* STDERR: add CR for LF */
+#endif
+ 
+ 
+#if (defined(RTE_Compiler_IO_TTY_ITM)    || \
+     defined(RTE_Compiler_IO_STDIN_ITM)  || \
+     defined(RTE_Compiler_IO_STDOUT_ITM) || \
+     defined(RTE_Compiler_IO_STDERR_ITM))
+ 
+/* ITM registers */
+#define ITM_PORT0_U8          (*((volatile uint8_t  *)0xE0000000))
+#define ITM_PORT0_U32         (*((volatile uint32_t *)0xE0000000))
+#define ITM_TER               (*((volatile uint32_t *)0xE0000E00))
+#define ITM_TCR               (*((volatile uint32_t *)0xE0000E80))
+ 
+#define ITM_TCR_ITMENA_Msk    (1UL << 0)
+ 
+/*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+#define ITM_RXBUFFER_EMPTY    0x5AA55AA5
+ 
+/*!< Variable to receive characters. */
+extern
+volatile int32_t ITM_RxBuffer;
+volatile int32_t ITM_RxBuffer = ITM_RXBUFFER_EMPTY;   
+ 
+/** \brief  ITM Send Character
+ 
+    The function transmits a character via the ITM channel 0, and
+    \li Just returns when no debugger is connected that has booked the output.
+    \li Is blocking when a debugger is connected, but the previous character
+        sent has not been transmitted.
+ 
+    \param [in]     ch  Character to transmit.
+ 
+    \returns            Character to transmit.
+ */
+int32_t ITM_SendChar (int32_t ch);
+int32_t ITM_SendChar (int32_t ch) {
+  if ((ITM_TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */
+      (ITM_TER & (1UL << 0)        )) { /* ITM Port #0 enabled */
+    while (ITM_PORT0_U32 == 0);
+    ITM_PORT0_U8 = (uint8_t)ch;
+  }
+  return (ch);
+}
+ 
+/** \brief  ITM Receive Character
+ 
+    The function inputs a character via the external variable \ref ITM_RxBuffer.
+    This variable is monitored and altered by the debugger to provide input.
+ 
+    \return             Received character.
+    \return         -1  No character pending.
+ */
+int32_t ITM_ReceiveChar (void);
+int32_t ITM_ReceiveChar (void) {
+  int32_t ch = -1;                      /* no character available */
+ 
+  if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) {
+    ch = ITM_RxBuffer;
+    ITM_RxBuffer = ITM_RXBUFFER_EMPTY;  /* ready for next character */
+  }
+ 
+  return (ch);
+}
+ 
+#endif  /* RTE_Compiler_IO_STDxxx_ITM */
+ 
+ 
+/**
+  Get a character from the stdio
+ 
+  \return     The next character from the input, or -1 on read error.
+*/
+#if   defined(RTE_Compiler_IO_STDIN)
+#if   defined(RTE_Compiler_IO_STDIN_User)
+extern int stdin_getchar (void);
+#elif defined(RTE_Compiler_IO_STDIN_ITM)
+static int stdin_getchar (void) {
+  int32_t ch;
+ 
+  do {
+    ch = ITM_ReceiveChar();
+  } while (ch == -1);
+  return (ch);
+}
+#elif defined(RTE_Compiler_IO_STDIN_BKPT)
+static int stdin_getchar (void) {
+  int32_t ch = -1;
+ 
+  __asm("BKPT 0");
+  return (ch);
+}
+#endif
+#endif
+ 
+ 
+/**
+  Put a character to the stdout
+ 
+  \param[in]   ch  Character to output
+  \return          The character written, or -1 on write error.
+*/
+#if   defined(RTE_Compiler_IO_STDOUT)
+#if   defined(RTE_Compiler_IO_STDOUT_User)
+// extern int stdout_putchar (int ch);
+static int stdout_putchar (int ch)
+{
+    unsigned char c = (unsigned char)ch;
+    SEGGER_RTT_Write(0, (const void*)&c, 1);
+    return ch;
+}
+
+#elif defined(RTE_Compiler_IO_STDOUT_ITM)
+static int stdout_putchar (int ch) {
+  return (ITM_SendChar(ch));
+}
+#elif defined(RTE_Compiler_IO_STDOUT_BKPT)
+static int stdout_putchar (int ch) {
+  __asm("BKPT 0");
+  return (ch);
+}
+#endif
+#endif
+ 
+ 
+/**
+  Put a character to the stderr
+ 
+  \param[in]   ch  Character to output
+  \return          The character written, or -1 on write error.
+*/
+#if   defined(RTE_Compiler_IO_STDERR)
+#if   defined(RTE_Compiler_IO_STDERR_User)
+extern int stderr_putchar (int ch);
+#elif defined(RTE_Compiler_IO_STDERR_ITM)
+static int stderr_putchar (int ch) {
+  return (ITM_SendChar(ch));
+}
+#elif defined(RTE_Compiler_IO_STDERR_BKPT)
+static int stderr_putchar (int ch) {
+  __asm("BKPT 0");
+  return (ch);
+}
+#endif
+#endif
+ 
+ 
+#ifdef __MICROLIB
+ 
+ 
+#ifdef RTE_Compiler_IO_STDIN
+static int getchar_undo =  0;
+static int getchar_ch   = -1;
+#endif
+ 
+ 
+/**
+   Writes the character specified by c (converted to an unsigned char) to
+   the output stream pointed to by stream, at the position indicated by the
+   asociated file position indicator (if defined), and advances the
+   indicator appropriately. If the file position indicator is not defined,
+   the character is appended to the output stream.
+ 
+  \param[in] c       Character
+  \param[in] stream  Stream handle
+ 
+  \return    The character written. If a write error occurs, the error
+             indicator is set and fputc returns EOF.
+*/
+__attribute__((weak))
+int fputc (int c, FILE * stream) {
+#if (!defined(RTE_Compiler_IO_STDOUT) && !defined(RTE_Compiler_IO_STDERR))
+  (void)c;
+  (void)stream;
+#endif
+ 
+#ifdef RTE_Compiler_IO_STDOUT
+  if (stream == &__stdout) {
+#if (STDOUT_CR_LF != 0)
+    if (c == '\n') stdout_putchar('\r');
+#endif
+    return (stdout_putchar(c));
+  }
+#endif
+ 
+#ifdef RTE_Compiler_IO_STDERR
+  if (stream == &__stderr) {
+#if (STDERR_CR_LF != 0)
+    if (c == '\n') stderr_putchar('\r');
+#endif
+    return (stderr_putchar(c));
+  }
+#endif
+ 
+  return (-1);
+}
+ 
+ 
+/**
+   Obtains the next character (if present) as an unsigned char converted to
+   an int, from the input stream pointed to by stream, and advances the
+   associated file position indicator (if defined).
+ 
+  \param[in] stream  Stream handle
+ 
+  \return    The next character from the input stream pointed to by stream.
+             If the stream is at end-of-file, the end-of-file indicator is
+             set and fgetc returns EOF. If a read error occurs, the error
+             indicator is set and fgetc returns EOF.
+*/
+__attribute__((weak))
+int fgetc (FILE * stream) {
+#ifdef RTE_Compiler_IO_STDIN
+  int ch;
+ 
+  if (stream == &__stdin) {
+    if (getchar_undo) {
+      ch = getchar_ch;
+      getchar_ch = -1;
+      getchar_undo = 0;
+      return (ch);
+    }
+    ch = stdin_getchar();
+#if (STDIN_ECHO != 0)
+    stdout_putchar(ch);
+#endif
+    getchar_ch = ch;
+    return (ch);
+  }
+#else
+  (void)stream;
+#endif
+ 
+  return (-1);
+}
+ 
+ 
+/**
+   The function __backspace() is used by the scanf family of functions, and must
+   be re-implemented if you retarget the stdio arrangements at the fgetc() level.
+ 
+  \param[in] stream  Stream handle
+ 
+  \return    The value returned by __backspace() is either 0 (success) or EOF
+             (failure). It returns EOF only if used incorrectly, for example,
+             if no characters have been read from the stream. When used 
+             correctly, __backspace() must always return 0, because the scanf
+             family of functions do not check the error return.
+*/
+__attribute__((weak))
+int __backspace(FILE *stream);
+int __backspace(FILE *stream) {
+ 
+#ifdef RTE_Compiler_IO_STDIN
+  if (stream == &__stdin) {
+    if (getchar_ch != -1) {
+      getchar_undo = 1;
+      return (0);
+    }
+    return (-1);
+  }
+#else
+  (void)stream;
+#endif
+ 
+  return (-1);
+}
+ 
+ 
+/**
+  Called from assert() and prints a message on stderr and calls abort().
+ 
+  \param[in] expr  assert expression that was not TRUE
+  \param[in] file  source file of the assertion
+  \param[in] line  source line of the assertion
+*/
+__attribute__((weak,noreturn))
+void __aeabi_assert (const char *expr, const char *file, int line) {
+  char str[12], *p;
+ 
+  fputs("*** assertion failed: ", stderr);
+  fputs(expr, stderr);
+  fputs(", file ", stderr);
+  fputs(file, stderr);
+  fputs(", line ", stderr);
+ 
+  p = str + sizeof(str);
+  *--p = '\0';
+  *--p = '\n';
+  while (line > 0) {
+    *--p = '0' + (line % 10);
+    line /= 10;
+  }
+  fputs(p, stderr);
+ 
+  abort();
+}
+ 
+ 
+__attribute__((weak))
+void abort(void) {
+  for (;;);
+}
+ 
+ 
+#else  /* __MICROLIB */
+ 
+ 
+#if (defined(RTE_Compiler_IO_STDIN)  || \
+     defined(RTE_Compiler_IO_STDOUT) || \
+     defined(RTE_Compiler_IO_STDERR) || \
+     defined(RTE_Compiler_IO_File))
+#define RETARGET_SYS
+ 
+/* IO device file handles. */
+#define FH_STDIN    0x8001
+#define FH_STDOUT   0x8002
+#define FH_STDERR   0x8003
+// User defined ...
+ 
+/* Standard IO device name defines. */
+const char __stdin_name[]  = ":STDIN";
+const char __stdout_name[] = ":STDOUT";
+const char __stderr_name[] = ":STDERR";
+ 
+#endif
+ 
+ 
+/**
+  Defined in rt_sys.h, this function opens a file.
+ 
+  The _sys_open() function is required by fopen() and freopen(). These
+  functions in turn are required if any file input/output function is to
+  be used.
+  The openmode parameter is a bitmap whose bits mostly correspond directly to
+  the ISO mode specification. Target-dependent extensions are possible, but
+  freopen() must also be extended.
+ 
+  \param[in] name     File name
+  \param[in] openmode Mode specification bitmap
+ 
+  \return    The return value is ֱ if an error occurs.
+*/
+#ifdef RETARGET_SYS
+__attribute__((weak))
+FILEHANDLE _sys_open (const char *name, int openmode) {
+#if (!defined(RTE_Compiler_IO_File))
+  (void)openmode;
+#endif
+ 
+  if (name == NULL) {
+    return (-1);
+  }
+ 
+  if (name[0] == ':') {
+    if (strcmp(name, ":STDIN") == 0) {
+      return (FH_STDIN);
+    }
+    if (strcmp(name, ":STDOUT") == 0) {
+      return (FH_STDOUT);
+    }
+    if (strcmp(name, ":STDERR") == 0) {
+      return (FH_STDERR);
+    }
+    return (-1);
+  }
+ 
+#ifdef RTE_Compiler_IO_File
+#ifdef RTE_Compiler_IO_File_FS
+  return (__sys_open(name, openmode));
+#endif
+#else
+  return (-1);
+#endif
+}
+#endif
+ 
+ 
+/**
+  Defined in rt_sys.h, this function closes a file previously opened
+  with _sys_open().
+  
+  This function must be defined if any input/output function is to be used.
+ 
+  \param[in] fh File handle
+ 
+  \return    The return value is 0 if successful. A nonzero value indicates
+             an error.
+*/
+#ifdef RETARGET_SYS
+__attribute__((weak))
+int _sys_close (FILEHANDLE fh) {
+ 
+  switch (fh) {
+    case FH_STDIN:
+      return (0);
+    case FH_STDOUT:
+      return (0);
+    case FH_STDERR:
+      return (0);
+  }
+ 
+#ifdef RTE_Compiler_IO_File
+#ifdef RTE_Compiler_IO_File_FS
+  return (__sys_close(fh));
+#endif
+#else
+  return (-1);
+#endif
+}
+#endif
+ 
+ 
+/**
+  Defined in rt_sys.h, this function writes the contents of a buffer to a file
+  previously opened with _sys_open().
+ 
+  \note The mode parameter is here for historical reasons. It contains
+        nothing useful and must be ignored.
+ 
+  \param[in] fh   File handle
+  \param[in] buf  Data buffer
+  \param[in] len  Data length
+  \param[in] mode Ignore this parameter
+ 
+  \return    The return value is either:
+             - a positive number representing the number of characters not
+               written (so any nonzero return value denotes a failure of
+               some sort)
+             - a negative number indicating an error.
+*/
+#ifdef RETARGET_SYS
+__attribute__((weak))
+int _sys_write (FILEHANDLE fh, const uint8_t *buf, uint32_t len, int mode) {
+#if (defined(RTE_Compiler_IO_STDOUT) || defined(RTE_Compiler_IO_STDERR))
+  int ch;
+#elif (!defined(RTE_Compiler_IO_File))
+  (void)buf;
+  (void)len;
+#endif
+  (void)mode;
+ 
+  switch (fh) {
+    case FH_STDIN:
+      return (-1);
+    case FH_STDOUT:
+#ifdef RTE_Compiler_IO_STDOUT
+      for (; len; len--) {
+        ch = *buf++;
+#if (STDOUT_CR_LF != 0)
+        if (ch == '\n') stdout_putchar('\r');
+#endif
+        stdout_putchar(ch);
+      }
+#endif
+      return (0);
+    case FH_STDERR:
+#ifdef RTE_Compiler_IO_STDERR
+      for (; len; len--) {
+        ch = *buf++;
+#if (STDERR_CR_LF != 0)
+        if (ch == '\n') stderr_putchar('\r');
+#endif
+        stderr_putchar(ch);
+      }
+#endif
+      return (0);
+  }
+ 
+#ifdef RTE_Compiler_IO_File
+#ifdef RTE_Compiler_IO_File_FS
+  return (__sys_write(fh, buf, len));
+#endif
+#else
+  return (-1);
+#endif
+}
+#endif
+ 
+ 
+/**
+  Defined in rt_sys.h, this function reads the contents of a file into a buffer.
+ 
+  Reading up to and including the last byte of data does not turn on the EOF
+  indicator. The EOF indicator is only reached when an attempt is made to read
+  beyond the last byte of data. The target-independent code is capable of
+  handling:
+    - the EOF indicator being returned in the same read as the remaining bytes
+      of data that precede the EOF
+    - the EOF indicator being returned on its own after the remaining bytes of
+      data have been returned in a previous read.
+ 
+  \note The mode parameter is here for historical reasons. It contains
+        nothing useful and must be ignored.
+ 
+  \param[in] fh   File handle
+  \param[in] buf  Data buffer
+  \param[in] len  Data length
+  \param[in] mode Ignore this parameter
+ 
+  \return     The return value is one of the following:
+              - The number of bytes not read (that is, len - result number of
+                bytes were read).
+              - An error indication.
+              - An EOF indicator. The EOF indication involves the setting of
+                0x80000000 in the normal result.
+*/
+#ifdef RETARGET_SYS
+__attribute__((weak))
+int _sys_read (FILEHANDLE fh, uint8_t *buf, uint32_t len, int mode) {
+#ifdef RTE_Compiler_IO_STDIN
+  int ch;
+#elif (!defined(RTE_Compiler_IO_File))
+  (void)buf;
+  (void)len;
+#endif
+  (void)mode;
+ 
+  switch (fh) {
+    case FH_STDIN:
+#ifdef RTE_Compiler_IO_STDIN
+      ch = stdin_getchar();
+      if (ch < 0) {
+        return ((int)(len | 0x80000000U));
+      }
+      *buf++ = (uint8_t)ch;
+#if (STDIN_ECHO != 0)
+      stdout_putchar(ch);
+#endif
+      len--;
+      return ((int)(len));
+#else
+      return ((int)(len | 0x80000000U));
+#endif
+    case FH_STDOUT:
+      return (-1);
+    case FH_STDERR:
+      return (-1);
+  }
+ 
+#ifdef RTE_Compiler_IO_File
+#ifdef RTE_Compiler_IO_File_FS
+  return (__sys_read(fh, buf, len));
+#endif
+#else
+  return (-1);
+#endif
+}
+#endif
+ 
+ 
+/**
+  Defined in rt_sys.h, this function writes a character to the console. The
+  console might have been redirected. You can use this function as a last
+  resort error handling routine.
+  
+  The default implementation of this function uses semihosting.
+  You can redefine this function, or __raise(), even if there is no other
+  input/output. For example, it might write an error message to a log kept
+  in nonvolatile memory.
+ 
+  \param[in] ch character to write
+*/
+#if   defined(RTE_Compiler_IO_TTY)
+#if   defined(RTE_Compiler_IO_TTY_User)
+extern void ttywrch (int ch);
+__attribute__((weak))
+void _ttywrch (int ch) {
+  ttywrch(ch);
+}
+#elif defined(RTE_Compiler_IO_TTY_ITM)
+__attribute__((weak))
+void _ttywrch (int ch) {
+  ITM_SendChar(ch);
+}
+#elif defined(RTE_Compiler_IO_TTY_BKPT)
+__attribute__((weak))
+void _ttywrch (int ch) {
+  (void)ch;
+  __asm("BKPT 0");
+}
+#endif
+#endif
+ 
+ 
+/**
+  Defined in rt_sys.h, this function determines if a file handle identifies
+  a terminal.
+ 
+  When a file is connected to a terminal device, this function is used to
+  provide unbuffered behavior by default (in the absence of a call to
+  set(v)buf) and to prohibit seeking.
+ 
+  \param[in] fh File handle
+ 
+  \return    The return value is one of the following values:
+             - 0:     There is no interactive device.
+             - 1:     There is an interactive device.
+             - other: An error occurred.
+*/
+#ifdef RETARGET_SYS
+__attribute__((weak))
+int _sys_istty (FILEHANDLE fh) {
+ 
+  switch (fh) {
+    case FH_STDIN:
+      return (1);
+    case FH_STDOUT:
+      return (1);
+    case FH_STDERR:
+      return (1);
+  }
+ 
+  return (0);
+}
+#endif
+ 
+ 
+/**
+  Defined in rt_sys.h, this function puts the file pointer at offset pos from
+  the beginning of the file.
+ 
+  This function sets the current read or write position to the new location pos
+  relative to the start of the current file fh.
+ 
+  \param[in] fh  File handle
+  \param[in] pos File pointer offset
+ 
+  \return    The result is:
+             - non-negative if no error occurs
+             - negative if an error occurs
+*/
+#ifdef RETARGET_SYS
+__attribute__((weak))
+int _sys_seek (FILEHANDLE fh, long pos) {
+#if (!defined(RTE_Compiler_IO_File))
+  (void)pos;
+#endif
+ 
+  switch (fh) {
+    case FH_STDIN:
+      return (-1);
+    case FH_STDOUT:
+      return (-1);
+    case FH_STDERR:
+      return (-1);
+  }
+ 
+#ifdef RTE_Compiler_IO_File
+#ifdef RTE_Compiler_IO_File_FS
+  return (__sys_seek(fh, (uint32_t)pos));
+#endif
+#else
+  return (-1);
+#endif
+}
+#endif
+ 
+ 
+/**
+  Defined in rt_sys.h, this function returns the current length of a file.
+ 
+  This function is used by _sys_seek() to convert an offset relative to the
+  end of a file into an offset relative to the beginning of the file.
+  You do not have to define _sys_flen() if you do not intend to use fseek().
+  If you retarget at system _sys_*() level, you must supply _sys_flen(),
+  even if the underlying system directly supports seeking relative to the
+  end of a file.
+ 
+  \param[in] fh File handle
+ 
+  \return    This function returns the current length of the file fh,
+             or a negative error indicator.
+*/
+#ifdef RETARGET_SYS
+__attribute__((weak))
+long _sys_flen (FILEHANDLE fh) {
+ 
+  switch (fh) {
+    case FH_STDIN:
+      return (0);
+    case FH_STDOUT:
+      return (0);
+    case FH_STDERR:
+      return (0);
+  }
+ 
+#ifdef RTE_Compiler_IO_File
+#ifdef RTE_Compiler_IO_File_FS
+  return (__sys_flen(fh));
+#endif
+#else
+  return (0);
+#endif
+}
+#endif
+ 
+ 
+#endif  /* __MICROLIB */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Jul 28 08:10:30 2016 +0000
@@ -0,0 +1,313 @@
+#include "mbed.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "slre.h"
+
+typedef uint8_t byte;
+
+DigitalOut myled(LED1); // PA_5
+DigitalOut led2(PC_8);
+
+
+static int static_total_tests = 0;
+static int static_failed_tests = 0;
+
+#define FAIL(str, line) do {                      \
+  printf("Fail on line %d: [%s]\n", line, str);   \
+  static_failed_tests++;                          \
+} while (0)
+
+#define ASSERT(expr) do {               \
+  static_total_tests++;                 \
+  if (!(expr)) FAIL(#expr, __LINE__);   \
+} while (0)
+
+/* Regex must have exactly one bracket pair */
+static char *slre_replace(const char *regex, const char *buf,
+                          const char *sub)
+{
+    char *s = NULL;
+    int n, n1, n2, n3, s_len, len = strlen(buf);
+    struct slre_cap cap = { NULL, 0 };
+
+    do {
+        s_len = s == NULL ? 0 : strlen(s);
+        if ((n = slre_match(regex, buf, len, &cap, 1, 0)) > 0) {
+            n1 = cap.ptr - buf, n2 = strlen(sub),
+            n3 = &buf[n] - &cap.ptr[cap.len];
+        } else {
+            n1 = len, n2 = 0, n3 = 0;
+        }
+        s = (char *) realloc(s, s_len + n1 + n2 + n3 + 1);
+        memcpy(s + s_len, buf, n1);
+        memcpy(s + s_len + n1, sub, n2);
+        memcpy(s + s_len + n1 + n2, cap.ptr + cap.len, n3);
+        s[s_len + n1 + n2 + n3] = '\0';
+
+        buf += n > 0 ? n : len;
+        len -= n > 0 ? n : len;
+    } while (len > 0);
+
+    return s;
+}
+
+
+uint32_t slre_test(void)
+{
+    struct slre_cap caps[10];
+
+    // reset test result counts;
+    static_total_tests = 0;
+    static_failed_tests = 0;
+
+    /* Metacharacters */
+    ASSERT(slre_match("$", "abcd", 4, NULL, 0, 0) == 4);
+    ASSERT(slre_match("^", "abcd", 4, NULL, 0, 0) == 0);
+    ASSERT(slre_match("x|^", "abcd", 4, NULL, 0, 0) == 0);
+    ASSERT(slre_match("x|$", "abcd", 4, NULL, 0, 0) == 4);
+    ASSERT(slre_match("x", "abcd", 4, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match(".", "abcd", 4, NULL, 0, 0) == 1);
+    ASSERT(slre_match("^.*\\\\.*$", "c:\\Tools", 8, NULL, 0, SLRE_IGNORE_CASE)
+           == 8);
+    ASSERT(slre_match("\\", "a", 1, NULL, 0, 0) == SLRE_INVALID_METACHARACTER);
+    ASSERT(slre_match("\\x", "a", 1, NULL, 0, 0) == SLRE_INVALID_METACHARACTER);
+    ASSERT(slre_match("\\x1", "a", 1, NULL, 0, 0) == SLRE_INVALID_METACHARACTER);
+    ASSERT(slre_match("\\x20", " ", 1, NULL, 0, 0) == 1);
+
+    ASSERT(slre_match("^.+$", "", 0, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match("^(.+)$", "", 0, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match("^([\\+-]?)([\\d]+)$", "+", 1,
+                      caps, 10, SLRE_IGNORE_CASE) == SLRE_NO_MATCH);
+    ASSERT(slre_match("^([\\+-]?)([\\d]+)$", "+27", 3,
+                      caps, 10, SLRE_IGNORE_CASE) == 3);
+    ASSERT(caps[0].len == 1);
+    ASSERT(caps[0].ptr[0] == '+');
+    ASSERT(caps[1].len == 2);
+    ASSERT(memcmp(caps[1].ptr, "27", 2) == 0);
+
+    ASSERT(slre_match("tel:\\+(\\d+[\\d-]+\\d)",
+                      "tel:+1-201-555-0123;a=b", 23, caps, 10, 0) == 19);
+    ASSERT(caps[0].len == 14);
+    ASSERT(memcmp(caps[0].ptr, "1-201-555-0123", 14) == 0);
+
+    /* Character sets */
+    ASSERT(slre_match("[abc]", "1c2", 3, NULL, 0, 0) == 2);
+    ASSERT(slre_match("[abc]", "1C2", 3, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match("[abc]", "1C2", 3, NULL, 0, SLRE_IGNORE_CASE) == 2);
+    ASSERT(slre_match("[.2]", "1C2", 3, NULL, 0, 0) == 1);
+    ASSERT(slre_match("[\\S]+", "ab cd", 5, NULL, 0, 0) == 2);
+    ASSERT(slre_match("[\\S]+\\s+[tyc]*", "ab cd", 5, NULL, 0, 0) == 4);
+    ASSERT(slre_match("[\\d]", "ab cd", 5, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match("[^\\d]", "ab cd", 5, NULL, 0, 0) == 1);
+    ASSERT(slre_match("[^\\d]+", "abc123", 6, NULL, 0, 0) == 3);
+    ASSERT(slre_match("[1-5]+", "123456789", 9, NULL, 0, 0) == 5);
+    ASSERT(slre_match("[1-5a-c]+", "123abcdef", 9, NULL, 0, 0) == 6);
+    ASSERT(slre_match("[1-5a-]+", "123abcdef", 9, NULL, 0, 0) == 4);
+    ASSERT(slre_match("[1-5a-]+", "123a--2oo", 9, NULL, 0, 0) == 7);
+    ASSERT(slre_match("[htps]+://", "https://", 8, NULL, 0, 0) == 8);
+    ASSERT(slre_match("[^\\s]+", "abc def", 7, NULL, 0, 0) == 3);
+    ASSERT(slre_match("[^fc]+", "abc def", 7, NULL, 0, 0) == 2);
+    ASSERT(slre_match("[^d\\sf]+", "abc def", 7, NULL, 0, 0) == 3);
+
+    /* Flags - case sensitivity */
+    ASSERT(slre_match("FO", "foo", 3, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match("FO", "foo", 3, NULL, 0, SLRE_IGNORE_CASE) == 2);
+    ASSERT(slre_match("(?m)FO", "foo", 3, NULL, 0, 0) ==
+           SLRE_UNEXPECTED_QUANTIFIER);
+    ASSERT(slre_match("(?m)x", "foo", 3, NULL, 0, 0) ==
+           SLRE_UNEXPECTED_QUANTIFIER);
+
+    ASSERT(slre_match("fo", "foo", 3, NULL, 0, 0) == 2);
+    ASSERT(slre_match(".+", "foo", 3, NULL, 0, 0) == 3);
+    ASSERT(slre_match(".+k", "fooklmn", 7, NULL, 0, 0) == 4);
+    ASSERT(slre_match(".+k.", "fooklmn", 7, NULL, 0, 0) == 5);
+    ASSERT(slre_match("p+", "fooklmn", 7, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match("ok", "fooklmn", 7, NULL, 0, 0) == 4);
+    ASSERT(slre_match("lmno", "fooklmn", 7, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match("mn.", "fooklmn", 7, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match("o", "fooklmn", 7, NULL, 0, 0) == 2);
+    ASSERT(slre_match("^o", "fooklmn", 7, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match("^", "fooklmn", 7, NULL, 0, 0) == 0);
+    ASSERT(slre_match("n$", "fooklmn", 7, NULL, 0, 0) == 7);
+    ASSERT(slre_match("n$k", "fooklmn", 7, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match("l$", "fooklmn", 7, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match(".$", "fooklmn", 7, NULL, 0, 0) == 7);
+    ASSERT(slre_match("a?", "fooklmn", 7, NULL, 0, 0) == 0);
+    ASSERT(slre_match("^a*CONTROL", "CONTROL", 7, NULL, 0, 0) == 7);
+    ASSERT(slre_match("^[a]*CONTROL", "CONTROL", 7, NULL, 0, 0) == 7);
+    ASSERT(slre_match("^(a*)CONTROL", "CONTROL", 7, NULL, 0, 0) == 7);
+    ASSERT(slre_match("^(a*)?CONTROL", "CONTROL", 7, NULL, 0, 0) == 7);
+
+    ASSERT(slre_match("\\_", "abc", 3, NULL, 0, 0) == SLRE_INVALID_METACHARACTER);
+    ASSERT(slre_match("+", "fooklmn", 7, NULL, 0, 0) == SLRE_UNEXPECTED_QUANTIFIER);
+    ASSERT(slre_match("()+", "fooklmn", 7, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match("\\x", "12", 2, NULL, 0, 0) == SLRE_INVALID_METACHARACTER);
+    ASSERT(slre_match("\\xhi", "12", 2, NULL, 0, 0) == SLRE_INVALID_METACHARACTER);
+    ASSERT(slre_match("\\x20", "_ J", 3, NULL, 0, 0) == 2);
+    ASSERT(slre_match("\\x4A", "_ J", 3, NULL, 0, 0) == 3);
+    ASSERT(slre_match("\\d+", "abc123def", 9, NULL, 0, 0) == 6);
+
+    /* Balancing brackets */
+    ASSERT(slre_match("(x))", "fooklmn", 7, NULL, 0, 0) == SLRE_UNBALANCED_BRACKETS);
+    ASSERT(slre_match("(", "fooklmn", 7, NULL, 0, 0) == SLRE_UNBALANCED_BRACKETS);
+
+    ASSERT(slre_match("klz?mn", "fooklmn", 7, NULL, 0, 0) == 7);
+    ASSERT(slre_match("fa?b", "fooklmn", 7, NULL, 0, 0) == SLRE_NO_MATCH);
+
+    /* Brackets & capturing */
+    ASSERT(slre_match("^(te)", "tenacity subdues all", 20, caps, 10, 0) == 2);
+    ASSERT(slre_match("(bc)", "abcdef", 6, caps, 10, 0) == 3);
+    ASSERT(slre_match(".(d.)", "abcdef", 6, caps, 10, 0) == 5);
+    ASSERT(slre_match(".(d.)\\)?", "abcdef", 6, caps, 10, 0) == 5);
+    ASSERT(caps[0].len == 2);
+    ASSERT(memcmp(caps[0].ptr, "de", 2) == 0);
+    ASSERT(slre_match("(.+)", "123", 3, caps, 10, 0) == 3);
+    ASSERT(slre_match("(2.+)", "123", 3, caps, 10, 0) == 3);
+    ASSERT(caps[0].len == 2);
+    ASSERT(memcmp(caps[0].ptr, "23", 2) == 0);
+    ASSERT(slre_match("(.+2)", "123", 3, caps, 10, 0) == 2);
+    ASSERT(caps[0].len == 2);
+    ASSERT(memcmp(caps[0].ptr, "12", 2) == 0);
+    ASSERT(slre_match("(.*(2.))", "123", 3, caps, 10, 0) == 3);
+    ASSERT(slre_match("(.)(.)", "123", 3, caps, 10, 0) == 2);
+    ASSERT(slre_match("(\\d+)\\s+(\\S+)", "12 hi", 5, caps, 10, 0) == 5);
+    ASSERT(slre_match("ab(cd)+ef", "abcdcdef", 8, NULL, 0, 0) == 8);
+    ASSERT(slre_match("ab(cd)*ef", "abcdcdef", 8, NULL, 0, 0) == 8);
+    ASSERT(slre_match("ab(cd)+?ef", "abcdcdef", 8, NULL, 0, 0) == 8);
+    ASSERT(slre_match("ab(cd)+?.", "abcdcdef", 8, NULL, 0, 0) == 5);
+    ASSERT(slre_match("ab(cd)?", "abcdcdef", 8, NULL, 0, 0) == 4);
+    ASSERT(slre_match("a(b)(cd)", "abcdcdef", 8, caps, 1, 0) ==
+           SLRE_CAPS_ARRAY_TOO_SMALL);
+    ASSERT(slre_match("(.+/\\d+\\.\\d+)\\.jpg$", "/foo/bar/12.34.jpg", 18,
+                      caps, 1, 0) == 18);
+    ASSERT(slre_match("(ab|cd).*\\.(xx|yy)", "ab.yy", 5, NULL, 0, 0) == 5);
+    ASSERT(slre_match(".*a", "abcdef", 6, NULL, 0, 0) == 1);
+    ASSERT(slre_match("(.+)c", "abcdef", 6, NULL, 0, 0) == 3);
+    ASSERT(slre_match("\\n", "abc\ndef", 7, NULL, 0, 0) == 4);
+    ASSERT(slre_match("b.\\s*\\n", "aa\r\nbb\r\ncc\r\n\r\n", 14,
+                      caps, 10, 0) == 8);
+
+    /* Greedy vs non-greedy */
+    ASSERT(slre_match(".+c", "abcabc", 6, NULL, 0, 0) == 6);
+    ASSERT(slre_match(".+?c", "abcabc", 6, NULL, 0, 0) == 3);
+    ASSERT(slre_match(".*?c", "abcabc", 6, NULL, 0, 0) == 3);
+    ASSERT(slre_match(".*c", "abcabc", 6, NULL, 0, 0) == 6);
+    ASSERT(slre_match("bc.d?k?b+", "abcabc", 6, NULL, 0, 0) == 5);
+
+    /* Branching */
+    ASSERT(slre_match("|", "abc", 3, NULL, 0, 0) == 0);
+    ASSERT(slre_match("|.", "abc", 3, NULL, 0, 0) == 1);
+    ASSERT(slre_match("x|y|b", "abc", 3, NULL, 0, 0) == 2);
+    ASSERT(slre_match("k(xx|yy)|ca", "abcabc", 6, NULL, 0, 0) == 4);
+    ASSERT(slre_match("k(xx|yy)|ca|bc", "abcabc", 6, NULL, 0, 0) == 3);
+    ASSERT(slre_match("(|.c)", "abc", 3, caps, 10, 0) == 3);
+    ASSERT(caps[0].len == 2);
+    ASSERT(memcmp(caps[0].ptr, "bc", 2) == 0);
+    ASSERT(slre_match("a|b|c", "a", 1, NULL, 0, 0) == 1);
+    ASSERT(slre_match("a|b|c", "b", 1, NULL, 0, 0) == 1);
+    ASSERT(slre_match("a|b|c", "c", 1, NULL, 0, 0) == 1);
+    ASSERT(slre_match("a|b|c", "d", 1, NULL, 0, 0) == SLRE_NO_MATCH);
+
+    /* Optional match at the end of the string */
+    ASSERT(slre_match("^.*c.?$", "abc", 3, NULL, 0, 0) == 3);
+    ASSERT(slre_match("^.*C.?$", "abc", 3, NULL, 0, SLRE_IGNORE_CASE) == 3);
+    ASSERT(slre_match("bk?", "ab", 2, NULL, 0, 0) == 2);
+    ASSERT(slre_match("b(k?)", "ab", 2, NULL, 0, 0) == 2);
+    ASSERT(slre_match("b[k-z]*", "ab", 2, NULL, 0, 0) == 2);
+    ASSERT(slre_match("ab(k|z|y)*", "ab", 2, NULL, 0, 0) == 2);
+    ASSERT(slre_match("[b-z].*", "ab", 2, NULL, 0, 0) == 2);
+    ASSERT(slre_match("(b|z|u).*", "ab", 2, NULL, 0, 0) == 2);
+    ASSERT(slre_match("ab(k|z|y)?", "ab", 2, NULL, 0, 0) == 2);
+    ASSERT(slre_match(".*", "ab", 2, NULL, 0, 0) == 2);
+    ASSERT(slre_match(".*$", "ab", 2, NULL, 0, 0) == 2);
+    ASSERT(slre_match("a+$", "aa", 2, NULL, 0, 0) == 2);
+    ASSERT(slre_match("a*$", "aa", 2, NULL, 0, 0) == 2);
+    ASSERT(slre_match( "a+$" ,"Xaa", 3, NULL, 0, 0) == 3);
+    ASSERT(slre_match( "a*$" ,"Xaa", 3, NULL, 0, 0) == 3);
+
+    /* Ignore case flag */
+    ASSERT(slre_match("[a-h]+", "abcdefghxxx", 11, NULL, 0, 0) == 8);
+    ASSERT(slre_match("[A-H]+", "ABCDEFGHyyy", 11, NULL, 0, 0) == 8);
+    ASSERT(slre_match("[a-h]+", "ABCDEFGHyyy", 11, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match("[A-H]+", "abcdefghyyy", 11, NULL, 0, 0) == SLRE_NO_MATCH);
+    ASSERT(slre_match("[a-h]+", "ABCDEFGHyyy", 11, NULL, 0, SLRE_IGNORE_CASE) == 8);
+    ASSERT(slre_match("[A-H]+", "abcdefghyyy", 11, NULL, 0, SLRE_IGNORE_CASE) == 8);
+
+    {
+        /* Example: HTTP request */
+        const char *request = " GET /index.html HTTP/1.0\r\n\r\n";
+        struct slre_cap caps[4];
+
+        if (slre_match("^\\s*(\\S+)\\s+(\\S+)\\s+HTTP/(\\d)\\.(\\d)",
+                       request, strlen(request), caps, 4, 0) > 0) {
+            printf("Method: [%.*s], URI: [%.*s]\n",
+                   caps[0].len, caps[0].ptr,
+                   caps[1].len, caps[1].ptr);
+        } else {
+            printf("Error parsing [%s]\n", request);
+        }
+
+        ASSERT(caps[1].len == 11);
+        ASSERT(memcmp(caps[1].ptr, "/index.html", caps[1].len) == 0);
+    }
+
+    {
+        /* Example: string replacement */
+        char *s = slre_replace("({{.+?}})",
+                               "Good morning, {{foo}}. How are you, {{bar}}?",
+                               "Bob");
+        printf("%s\n", s);
+        ASSERT(strcmp(s, "Good morning, Bob. How are you, Bob?") == 0);
+        free(s);
+    }
+
+    {
+        /* Example: find all URLs in a string */
+        static const char *str =
+            "<img src=\"HTTPS://FOO.COM/x?b#c=tab1\"/> "
+            "  <a href=\"http://cesanta.com\">some link</a>";
+
+        static const char *regex = "((https?://)[^\\s/'\"<>]+/?[^\\s'\"<>]*)";
+        struct slre_cap caps[2];
+        int i, j = 0, str_len = (int) strlen(str);
+
+        while (j < str_len &&
+                (i = slre_match(regex, str + j, str_len - j, caps, 2, SLRE_IGNORE_CASE)) > 0) {
+            printf("Found URL: [%.*s]\n", caps[0].len, caps[0].ptr);
+            j += i;
+        }
+    }
+
+    {
+        /* Example more complex regular expression */
+        static const char * str = "aa 1234 xy\nxyz";
+        static const char * regex = "aa ([0-9]*) *([x-z]*)\\s+xy([yz])";
+        struct slre_cap caps[3];
+        ASSERT(slre_match(regex, str, strlen(str), caps, 3, 0) > 0);
+        ASSERT(caps[0].len == 4);
+        ASSERT(caps[1].len == 2);
+        ASSERT(caps[2].len == 1);
+        ASSERT(caps[2].ptr[0] == 'z');
+    }
+
+    printf("Unit test %s (total test: %d, failed tests: %d)\n",
+           static_failed_tests > 0 ? "FAILED" : "PASSED",
+           static_total_tests, static_failed_tests);
+
+    return static_failed_tests == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+
+int main(void)
+{
+    while (true) {
+        uint32_t result = slre_test();
+        printf("SLRE TEST RESULT : %s\r\n", (result == EXIT_SUCCESS) ? "SUCCESS" : "FAILURE");
+        printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r\n\r\n");
+        led2 = !led2;
+        wait(1.0);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Jul 28 08:10:30 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/f9eeca106725
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/slre/slre.c	Thu Jul 28 08:10:30 2016 +0000
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
+ * Copyright (c) 2013 Cesanta Software Limited
+ * All rights reserved
+ *
+ * This library is dual-licensed: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. For the terms of this
+ * license, see <http://www.gnu.org/licenses/>.
+ *
+ * You are free to use this library under the terms of the GNU General
+ * Public License, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * Alternatively, you can license this library under a commercial
+ * license, as set out in <http://cesanta.com/products.html>.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "slre.h"
+
+#define MAX_BRANCHES 100
+#define MAX_BRACKETS 100
+#define FAIL_IF(condition, error_code) if (condition) return (error_code)
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(ar) (sizeof(ar) / sizeof((ar)[0]))
+#endif
+
+#ifdef SLRE_DEBUG
+#define DBG(x) printf x
+#else
+#define DBG(x)
+#endif
+
+struct bracket_pair {
+  const char *ptr;  /* Points to the first char after '(' in regex  */
+  int len;          /* Length of the text between '(' and ')'       */
+  int branches;     /* Index in the branches array for this pair    */
+  int num_branches; /* Number of '|' in this bracket pair           */
+};
+
+struct branch {
+  int bracket_index;    /* index for 'struct bracket_pair brackets' */
+                        /* array defined below                      */
+  const char *schlong;  /* points to the '|' character in the regex */
+};
+
+struct regex_info {
+  /*
+   * Describes all bracket pairs in the regular expression.
+   * First entry is always present, and grabs the whole regex.
+   */
+  struct bracket_pair brackets[MAX_BRACKETS];
+  int num_brackets;
+
+  /*
+   * Describes alternations ('|' operators) in the regular expression.
+   * Each branch falls into a specific branch pair.
+   */
+  struct branch branches[MAX_BRANCHES];
+  int num_branches;
+
+  /* Array of captures provided by the user */
+  struct slre_cap *caps;
+  int num_caps;
+
+  /* E.g. SLRE_IGNORE_CASE. See enum below */
+  int flags;
+};
+
+static int is_metacharacter(const unsigned char *s) {
+  static const char *metacharacters = "^$().[]*+?|\\Ssdbfnrtv";
+  return strchr(metacharacters, *s) != NULL;
+}
+
+static int op_len(const char *re) {
+  return re[0] == '\\' && re[1] == 'x' ? 4 : re[0] == '\\' ? 2 : 1;
+}
+
+static int set_len(const char *re, int re_len) {
+  int len = 0;
+
+  while (len < re_len && re[len] != ']') {
+    len += op_len(re + len);
+  }
+
+  return len <= re_len ? len + 1 : -1;
+}
+
+static int get_op_len(const char *re, int re_len) {
+  return re[0] == '[' ? set_len(re + 1, re_len - 1) + 1 : op_len(re);
+}
+
+static int is_quantifier(const char *re) {
+  return re[0] == '*' || re[0] == '+' || re[0] == '?';
+}
+
+static int toi(int x) {
+  return isdigit(x) ? x - '0' : x - 'W';
+}
+
+static int hextoi(const unsigned char *s) {
+  return (toi(tolower(s[0])) << 4) | toi(tolower(s[1]));
+}
+
+static int match_op(const unsigned char *re, const unsigned char *s,
+                    struct regex_info *info) {
+  int result = 0;
+  switch (*re) {
+    case '\\':
+      /* Metacharacters */
+      switch (re[1]) {
+        case 'S': FAIL_IF(isspace(*s), SLRE_NO_MATCH); result++; break;
+        case 's': FAIL_IF(!isspace(*s), SLRE_NO_MATCH); result++; break;
+        case 'd': FAIL_IF(!isdigit(*s), SLRE_NO_MATCH); result++; break;
+        case 'b': FAIL_IF(*s != '\b', SLRE_NO_MATCH); result++; break;
+        case 'f': FAIL_IF(*s != '\f', SLRE_NO_MATCH); result++; break;
+        case 'n': FAIL_IF(*s != '\n', SLRE_NO_MATCH); result++; break;
+        case 'r': FAIL_IF(*s != '\r', SLRE_NO_MATCH); result++; break;
+        case 't': FAIL_IF(*s != '\t', SLRE_NO_MATCH); result++; break;
+        case 'v': FAIL_IF(*s != '\v', SLRE_NO_MATCH); result++; break;
+
+        case 'x':
+          /* Match byte, \xHH where HH is hexadecimal byte representaion */
+          FAIL_IF(hextoi(re + 2) != *s, SLRE_NO_MATCH);
+          result++;
+          break;
+
+        default:
+          /* Valid metacharacter check is done in bar() */
+          FAIL_IF(re[1] != s[0], SLRE_NO_MATCH);
+          result++;
+          break;
+      }
+      break;
+
+    case '|': FAIL_IF(1, SLRE_INTERNAL_ERROR); break;
+    case '$': FAIL_IF(1, SLRE_NO_MATCH); break;
+    case '.': result++; break;
+
+    default:
+      if (info->flags & SLRE_IGNORE_CASE) {
+        FAIL_IF(tolower(*re) != tolower(*s), SLRE_NO_MATCH);
+      } else {
+        FAIL_IF(*re != *s, SLRE_NO_MATCH);
+      }
+      result++;
+      break;
+  }
+
+  return result;
+}
+
+static int match_set(const char *re, int re_len, const char *s,
+                     struct regex_info *info) {
+  int len = 0, result = -1, invert = re[0] == '^';
+
+  if (invert) re++, re_len--;
+
+  while (len <= re_len && re[len] != ']' && result <= 0) {
+    /* Support character range */
+    if (re[len] != '-' && re[len + 1] == '-' && re[len + 2] != ']' &&
+        re[len + 2] != '\0') {
+      result = info->flags &  SLRE_IGNORE_CASE ?
+        tolower(*s) >= tolower(re[len]) && tolower(*s) <= tolower(re[len + 2]) :
+        *s >= re[len] && *s <= re[len + 2];
+      len += 3;
+    } else {
+      result = match_op((unsigned char *) re + len, (unsigned char *) s, info);
+      len += op_len(re + len);
+    }
+  }
+  return (!invert && result > 0) || (invert && result <= 0) ? 1 : -1;
+}
+
+static int doh(const char *s, int s_len, struct regex_info *info, int bi);
+
+static int bar(const char *re, int re_len, const char *s, int s_len,
+               struct regex_info *info, int bi) {
+  /* i is offset in re, j is offset in s, bi is brackets index */
+  int i, j, n, step;
+
+  for (i = j = 0; i < re_len && j <= s_len; i += step) {
+
+    /* Handle quantifiers. Get the length of the chunk. */
+    step = re[i] == '(' ? info->brackets[bi + 1].len + 2 :
+      get_op_len(re + i, re_len - i);
+
+    DBG(("%s [%.*s] [%.*s] re_len=%d step=%d i=%d j=%d\n", __func__,
+         re_len - i, re + i, s_len - j, s + j, re_len, step, i, j));
+
+    FAIL_IF(is_quantifier(&re[i]), SLRE_UNEXPECTED_QUANTIFIER);
+    FAIL_IF(step <= 0, SLRE_INVALID_CHARACTER_SET);
+
+    if (i + step < re_len && is_quantifier(re + i + step)) {
+      DBG(("QUANTIFIER: [%.*s]%c [%.*s]\n", step, re + i,
+           re[i + step], s_len - j, s + j));
+      if (re[i + step] == '?') {
+        int result = bar(re + i, step, s + j, s_len - j, info, bi);
+        j += result > 0 ? result : 0;
+        i++;
+      } else if (re[i + step] == '+' || re[i + step] == '*') {
+        int j2 = j, nj = j, n1, n2 = -1, ni, non_greedy = 0;
+
+        /* Points to the regexp code after the quantifier */
+        ni = i + step + 1;
+        if (ni < re_len && re[ni] == '?') {
+          non_greedy = 1;
+          ni++;
+        }
+
+        do {
+          if ((n1 = bar(re + i, step, s + j2, s_len - j2, info, bi)) > 0) {
+            j2 += n1;
+          }
+          if (re[i + step] == '+' && n1 < 0) break;
+
+          if (ni >= re_len) {
+            /* After quantifier, there is nothing */
+            nj = j2;
+          } else if ((n2 = bar(re + ni, re_len - ni, s + j2,
+                               s_len - j2, info, bi)) >= 0) {
+            /* Regex after quantifier matched */
+            nj = j2 + n2;
+          }
+          if (nj > j && non_greedy) break;
+        } while (n1 > 0);
+
+        /*
+         * Even if we found one or more pattern, this branch will be executed,
+         * changing the next captures.
+         */
+        if (n1 < 0 && n2 < 0 && re[i + step] == '*' &&
+            (n2 = bar(re + ni, re_len - ni, s + j, s_len - j, info, bi)) > 0) {
+          nj = j + n2;
+        }
+
+        DBG(("STAR/PLUS END: %d %d %d %d %d\n", j, nj, re_len - ni, n1, n2));
+        FAIL_IF(re[i + step] == '+' && nj == j, SLRE_NO_MATCH);
+
+        /* If while loop body above was not executed for the * quantifier,  */
+        /* make sure the rest of the regex matches                          */
+        FAIL_IF(nj == j && ni < re_len && n2 < 0, SLRE_NO_MATCH);
+
+        /* Returning here cause we've matched the rest of RE already */
+        return nj;
+      }
+      continue;
+    }
+
+    if (re[i] == '[') {
+      n = match_set(re + i + 1, re_len - (i + 2), s + j, info);
+      DBG(("SET %.*s [%.*s] -> %d\n", step, re + i, s_len - j, s + j, n));
+      FAIL_IF(n <= 0, SLRE_NO_MATCH);
+      j += n;
+    } else if (re[i] == '(') {
+      n = SLRE_NO_MATCH;
+      bi++;
+      FAIL_IF(bi >= info->num_brackets, SLRE_INTERNAL_ERROR);
+      DBG(("CAPTURING [%.*s] [%.*s] [%s]\n",
+           step, re + i, s_len - j, s + j, re + i + step));
+
+      if (re_len - (i + step) <= 0) {
+        /* Nothing follows brackets */
+        n = doh(s + j, s_len - j, info, bi);
+      } else {
+        int j2;
+        for (j2 = 0; j2 <= s_len - j; j2++) {
+          if ((n = doh(s + j, s_len - (j + j2), info, bi)) >= 0 &&
+              bar(re + i + step, re_len - (i + step),
+                  s + j + n, s_len - (j + n), info, bi) >= 0) break;
+        }
+      }
+
+      DBG(("CAPTURED [%.*s] [%.*s]:%d\n", step, re + i, s_len - j, s + j, n));
+      FAIL_IF(n < 0, n);
+      if (info->caps != NULL && n > 0) {
+        info->caps[bi - 1].ptr = s + j;
+        info->caps[bi - 1].len = n;
+      }
+      j += n;
+    } else if (re[i] == '^') {
+      FAIL_IF(j != 0, SLRE_NO_MATCH);
+    } else if (re[i] == '$') {
+      FAIL_IF(j != s_len, SLRE_NO_MATCH);
+    } else {
+      FAIL_IF(j >= s_len, SLRE_NO_MATCH);
+      n = match_op((unsigned char *) (re + i), (unsigned char *) (s + j), info);
+      FAIL_IF(n <= 0, n);
+      j += n;
+    }
+  }
+
+  return j;
+}
+
+/* Process branch points */
+static int doh(const char *s, int s_len, struct regex_info *info, int bi) {
+  const struct bracket_pair *b = &info->brackets[bi];
+  int i = 0, len, result;
+  const char *p;
+
+  do {
+    p = i == 0 ? b->ptr : info->branches[b->branches + i - 1].schlong + 1;
+    len = b->num_branches == 0 ? b->len :
+      i == b->num_branches ? (int) (b->ptr + b->len - p) :
+      (int) (info->branches[b->branches + i].schlong - p);
+    DBG(("%s %d %d [%.*s] [%.*s]\n", __func__, bi, i, len, p, s_len, s));
+    result = bar(p, len, s, s_len, info, bi);
+    DBG(("%s <- %d\n", __func__, result));
+  } while (result <= 0 && i++ < b->num_branches);  /* At least 1 iteration */
+
+  return result;
+}
+
+static int baz(const char *s, int s_len, struct regex_info *info) {
+  int i, result = -1, is_anchored = info->brackets[0].ptr[0] == '^';
+
+  for (i = 0; i <= s_len; i++) {
+    result = doh(s + i, s_len - i, info, 0);
+    if (result >= 0) {
+      result += i;
+      break;
+    }
+    if (is_anchored) break;
+  }
+
+  return result;
+}
+
+static void setup_branch_points(struct regex_info *info) {
+  int i, j;
+  struct branch tmp;
+
+  /* First, sort branches. Must be stable, no qsort. Use bubble algo. */
+  for (i = 0; i < info->num_branches; i++) {
+    for (j = i + 1; j < info->num_branches; j++) {
+      if (info->branches[i].bracket_index > info->branches[j].bracket_index) {
+        tmp = info->branches[i];
+        info->branches[i] = info->branches[j];
+        info->branches[j] = tmp;
+      }
+    }
+  }
+
+  /*
+   * For each bracket, set their branch points. This way, for every bracket
+   * (i.e. every chunk of regex) we know all branch points before matching.
+   */
+  for (i = j = 0; i < info->num_brackets; i++) {
+    info->brackets[i].num_branches = 0;
+    info->brackets[i].branches = j;
+    while (j < info->num_branches && info->branches[j].bracket_index == i) {
+      info->brackets[i].num_branches++;
+      j++;
+    }
+  }
+}
+
+static int foo(const char *re, int re_len, const char *s, int s_len,
+               struct regex_info *info) {
+  int i, step, depth = 0;
+
+  /* First bracket captures everything */
+  info->brackets[0].ptr = re;
+  info->brackets[0].len = re_len;
+  info->num_brackets = 1;
+
+  /* Make a single pass over regex string, memorize brackets and branches */
+  for (i = 0; i < re_len; i += step) {
+    step = get_op_len(re + i, re_len - i);
+
+    if (re[i] == '|') {
+      FAIL_IF(info->num_branches >= (int) ARRAY_SIZE(info->branches),
+              SLRE_TOO_MANY_BRANCHES);
+      info->branches[info->num_branches].bracket_index =
+        info->brackets[info->num_brackets - 1].len == -1 ?
+        info->num_brackets - 1 : depth;
+      info->branches[info->num_branches].schlong = &re[i];
+      info->num_branches++;
+    } else if (re[i] == '\\') {
+      FAIL_IF(i >= re_len - 1, SLRE_INVALID_METACHARACTER);
+      if (re[i + 1] == 'x') {
+        /* Hex digit specification must follow */
+        FAIL_IF(re[i + 1] == 'x' && i >= re_len - 3,
+                SLRE_INVALID_METACHARACTER);
+        FAIL_IF(re[i + 1] ==  'x' && !(isxdigit(re[i + 2]) &&
+                isxdigit(re[i + 3])), SLRE_INVALID_METACHARACTER);
+      } else {
+        FAIL_IF(!is_metacharacter((unsigned char *) re + i + 1),
+                SLRE_INVALID_METACHARACTER);
+      }
+    } else if (re[i] == '(') {
+      FAIL_IF(info->num_brackets >= (int) ARRAY_SIZE(info->brackets),
+              SLRE_TOO_MANY_BRACKETS);
+      depth++;  /* Order is important here. Depth increments first. */
+      info->brackets[info->num_brackets].ptr = re + i + 1;
+      info->brackets[info->num_brackets].len = -1;
+      info->num_brackets++;
+      FAIL_IF(info->num_caps > 0 && info->num_brackets - 1 > info->num_caps,
+              SLRE_CAPS_ARRAY_TOO_SMALL);
+    } else if (re[i] == ')') {
+      int ind = info->brackets[info->num_brackets - 1].len == -1 ?
+        info->num_brackets - 1 : depth;
+      info->brackets[ind].len = (int) (&re[i] - info->brackets[ind].ptr);
+      DBG(("SETTING BRACKET %d [%.*s]\n",
+           ind, info->brackets[ind].len, info->brackets[ind].ptr));
+      depth--;
+      FAIL_IF(depth < 0, SLRE_UNBALANCED_BRACKETS);
+      FAIL_IF(i > 0 && re[i - 1] == '(', SLRE_NO_MATCH);
+    }
+  }
+
+  FAIL_IF(depth != 0, SLRE_UNBALANCED_BRACKETS);
+  setup_branch_points(info);
+
+  return baz(s, s_len, info);
+}
+
+int slre_match(const char *regexp, const char *s, int s_len,
+               struct slre_cap *caps, int num_caps, int flags) {
+  struct regex_info info;
+
+  /* Initialize info structure */
+  info.flags = flags;
+  info.num_brackets = info.num_branches = 0;
+  info.num_caps = num_caps;
+  info.caps = caps;
+
+  DBG(("========================> [%s] [%.*s]\n", regexp, s_len, s));
+  return foo(regexp, (int) strlen(regexp), s, s_len, &info);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/slre/slre.h	Thu Jul 28 08:10:30 2016 +0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
+ * Copyright (c) 2013 Cesanta Software Limited
+ * All rights reserved
+ *
+ * This library is dual-licensed: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. For the terms of this
+ * license, see <http://www.gnu.org/licenses/>.
+ *
+ * You are free to use this library under the terms of the GNU General
+ * Public License, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * Alternatively, you can license this library under a commercial
+ * license, as set out in <http://cesanta.com/products.html>.
+ */
+
+/*
+ * This is a regular expression library that implements a subset of Perl RE.
+ * Please refer to README.md for a detailed reference.
+ */
+
+#ifndef CS_SLRE_SLRE_H_
+#define CS_SLRE_SLRE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct slre_cap {
+  const char *ptr;
+  int len;
+};
+
+
+int slre_match(const char *regexp, const char *buf, int buf_len,
+               struct slre_cap *caps, int num_caps, int flags);
+
+/* Possible flags for slre_match() */
+enum { SLRE_IGNORE_CASE = 1 };
+
+
+/* slre_match() failure codes */
+#define SLRE_NO_MATCH               -1
+#define SLRE_UNEXPECTED_QUANTIFIER  -2
+#define SLRE_UNBALANCED_BRACKETS    -3
+#define SLRE_INTERNAL_ERROR         -4
+#define SLRE_INVALID_CHARACTER_SET  -5
+#define SLRE_INVALID_METACHARACTER  -6
+#define SLRE_CAPS_ARRAY_TOO_SMALL   -7
+#define SLRE_TOO_MANY_BRANCHES      -8
+#define SLRE_TOO_MANY_BRACKETS      -9
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CS_SLRE_SLRE_H_ */