in build/VisualStudio/target-specific-source/logging_output_windows.c [264:379]
void vTCPLoggingPrintf( const char * pcFormat,
... )
{
char cPrintString[ dlMAX_PRINT_STRING_LENGTH ];
char cOutputString[ dlMAX_PRINT_STRING_LENGTH ];
char * pcSource, * pcTarget, * pcBegin;
size_t xSpaceInBuffer, rc;
int32_t iLength;
static BaseType_t xMessageNumber = 0;
static BaseType_t xAfterLineBreak = pdTRUE;
va_list args;
uint32_t ulIPAddress;
const char * pcTaskName;
const char * pcNoTask = "None";
/* There are a variable number of parameters. */
va_start( args, pcFormat );
/* Additional info to place at the start of the log. */
if( xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED )
{
pcTaskName = pcTaskGetName( NULL );
}
else
{
pcTaskName = pcNoTask;
}
/* There are a variable number of parameters. */
va_start( args, pcFormat );
vsnprintf( cPrintString, dlMAX_PRINT_STRING_LENGTH, pcFormat, args );
va_end( args );
/* For ease of viewing, copy the string into another buffer, converting
* IP addresses to dot notation on the way. Leave space at the beginning
* of the buffer to hold the message length. */
pcSource = cPrintString;
pcTarget = cOutputString + iMessageLengthBytes;
while( ( *pcSource ) != '\0' )
{
*pcTarget = *pcSource;
pcTarget++;
pcSource++;
/* Look forward for an IP address denoted by 'ip'. */
if( ( isxdigit( ( int ) pcSource[ 0 ] ) != pdFALSE ) && ( pcSource[ 1 ] == 'i' ) && ( pcSource[ 2 ] == 'p' ) )
{
*pcTarget = *pcSource;
pcTarget++;
*pcTarget = '\0';
pcBegin = pcTarget - 8;
while( ( pcTarget > pcBegin ) && ( isxdigit( ( int ) pcTarget[ -1 ] ) != pdFALSE ) )
{
pcTarget--;
}
sscanf( pcTarget, "%8X", ( unsigned int * ) &ulIPAddress );
rc = sprintf( pcTarget, "%lu.%lu.%lu.%lu",
( unsigned long ) ( ulIPAddress >> 24UL ),
( unsigned long ) ( ( ulIPAddress >> 16UL ) & 0xffUL ),
( unsigned long ) ( ( ulIPAddress >> 8UL ) & 0xffUL ),
( unsigned long ) ( ulIPAddress & 0xffUL ) );
pcTarget += rc;
pcSource += 3; /* skip "<n>ip" */
}
}
/* How far through the buffer was written? */
iLength = ( int32_t ) ( pcTarget - cOutputString );
/* Adjust for the fact that space was left at the beginning of the buffer
* to hold the message length. */
iLength -= iMessageLengthBytes;
/* Write the message length in the beginning of the buffer. */
memcpy( cOutputString, &iLength, iMessageLengthBytes );
configASSERT( xLogStreamBuffer );
/* How much space is in the buffer? */
if( xSemaphoreTake( xStreamBufferMutex, dlMAX_SEMAPHORE_WAIT_TIME ) != pdFAIL )
{
xSpaceInBuffer = uxStreamBufferGetSpace( xLogStreamBuffer );
if( xSpaceInBuffer >= ( size_t ) ( iLength + iMessageLengthBytes ) )
{
/* The calling task can access the stream buffer because it holds the
* mutex but must also raise its priority to be above the priority of the
* windows thread that reads from the stream buffer. */
uxStreamBufferAdd( xLogStreamBuffer, 0, ( const uint8_t * ) cOutputString, ( size_t ) ( iLength + iMessageLengthBytes ) );
/* xDirectPrint is initialized to pdTRUE, and while it remains true the
* logging output function is called directly. When the system is running
* the output function cannot be called directly because it would get
* called from both FreeRTOS tasks and Win32 threads - so instead wake the
* Win32 thread responsible for the actual output. */
if( xDirectPrint != pdFALSE )
{
/* While starting up, the thread which calls prvWin32LoggingThread()
* is not running yet and xDirectPrint will be pdTRUE. */
prvLoggingFlushBuffer();
}
else if( pvLoggingThreadEvent != NULL )
{
/* While running, wake up prvWin32LoggingThread() to send the
* logging data. */
SetEvent( pvLoggingThreadEvent );
}
}
xSemaphoreGive( xStreamBufferMutex );
}
}