void vTCPLoggingPrintf()

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 );
    }
}