📄 ustdlib.c
字号:
//*****************************************************************************
//
// ustdlib.c - Simple standard library functions.
//
// Copyright (c) 2007-2008 Luminary Micro, Inc. All rights reserved.
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. You may not combine
// this software with "viral" open-source software in order to form a larger
// program. Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 3618 of the Stellaris Firmware Development Package.
//
//*****************************************************************************
#include <string.h>
#include "debug.h"
#include "ustdlib.h"
//*****************************************************************************
//
//! \addtogroup ustdlib_api
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
// A mapping from an integer between 0 and 15 to its ASCII character
// equivalent.
//
//*****************************************************************************
static const char * const g_pcHex = "0123456789abcdef";
//*****************************************************************************
//
//! A simple vsnprintf function supporting \%c, \%d, \%p, \%s, \%u, \%x, and
//! \%X.
//!
//! \param pcBuf points to the buffer where the converted string is stored.
//! \param ulSize is the size of the buffer.
//! \param pcString is the format string.
//! \param vaArgP is the list of optional arguments, which depend on the
//! contents of the format string.
//!
//! This function is very similar to the C library <tt>vsnprintf()</tt>
//! function. Only the following formatting characters are supported:
//!
//! - \%c to print a character
//! - \%d to print a decimal value
//! - \%s to print a string
//! - \%u to print an unsigned decimal value
//! - \%x to print a hexadecimal value using lower case letters
//! - \%X to print a hexadecimal value using lower case letters (not upper case
//! letters as would typically be used)
//! - \%p to print a pointer as a hexadecimal value
//! - \%\% to print out a \% character
//!
//! For \%d, \%p, \%s, \%u, \%x, and \%X, an optional number may reside between
//! the \% and the format character, which specifies the minimum number of
//! characters to use for that value; if preceded by a 0 then the extra
//! characters will be filled with zeros instead of spaces. For example,
//! ``\%8d'' will use eight characters to print the decimal value with spaces
//! added to reach eight; ``\%08d'' will use eight characters as well but will
//! add zeroes instead of spaces.
//!
//! The type of the arguments after \e pcString must match the requirements of
//! the format string. For example, if an integer was passed where a string
//! was expected, an error of some kind will most likely occur.
//!
//! The \e ulSize parameter limits the number of characters that will be stored
//! in the buffer pointed to by \e pcBuf to prevent the possibility of a buffer
//! overflow. The buffer size should be large enough to hold the expected
//! converted output string, including the null termination character.
//!
//! The function will return the number of characters that would be converted
//! as if there were no limit on the buffer size. Therefore it is possible for
//! the function to return a count that is greater than the specified buffer
//! size. If this happens, it means that the output was truncated.
//!
//! \return Returns the number of characters that were to be stored, not
//! including the NULL termination character, regardless of space in the
//! buffer.
//
//*****************************************************************************
int
uvsnprintf(char *pcBuf, unsigned long ulSize, const char *pcString,
va_list vaArgP)
{
unsigned long ulIdx, ulValue, ulCount, ulBase, ulNeg;
char *pcStr, cFill;
int iConvertCount = 0;
//
// Check the arguments.
//
ASSERT(pcString != 0);
ASSERT(pcBuf != 0);
ASSERT(ulSize != 0);
//
// Adjust buffer size limit to allow one space for null termination.
//
if(ulSize)
{
ulSize--;
}
//
// Initialize the count of characters converted.
//
iConvertCount = 0;
//
// Loop while there are more characters in the format string.
//
while(*pcString)
{
//
// Find the first non-% character, or the end of the string.
//
for(ulIdx = 0; (pcString[ulIdx] != '%') && (pcString[ulIdx] != '\0');
ulIdx++)
{
}
//
// Write this portion of the string to the output buffer. If there are
// more characters to write than there is space in the buffer, then
// only write as much as will fit in the buffer.
//
if(ulIdx > ulSize)
{
strncpy(pcBuf, pcString, ulSize);
pcBuf += ulSize;
ulSize = 0;
}
else
{
strncpy(pcBuf, pcString, ulIdx);
pcBuf += ulIdx;
ulSize -= ulIdx;
}
//
// Update the conversion count. This will be the number of characters
// that should have been written, even if there was not room in the
// buffer.
//
iConvertCount += ulIdx;
//
// Skip the portion of the format string that was written.
//
pcString += ulIdx;
//
// See if the next character is a %.
//
if(*pcString == '%')
{
//
// Skip the %.
//
pcString++;
//
// Set the digit count to zero, and the fill character to space
// (that is, to the defaults).
//
ulCount = 0;
cFill = ' ';
//
// It may be necessary to get back here to process more characters.
// Goto's aren't pretty, but effective. I feel extremely dirty for
// using not one but two of the beasts.
//
again:
//
// Determine how to handle the next character.
//
switch(*pcString++)
{
//
// Handle the digit characters.
//
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
//
// If this is a zero, and it is the first digit, then the
// fill character is a zero instead of a space.
//
if((pcString[-1] == '0') && (ulCount == 0))
{
cFill = '0';
}
//
// Update the digit count.
//
ulCount *= 10;
ulCount += pcString[-1] - '0';
//
// Get the next character.
//
goto again;
}
//
// Handle the %c command.
//
case 'c':
{
//
// Get the value from the varargs.
//
ulValue = va_arg(vaArgP, unsigned long);
//
// Copy the character to the output buffer, if there is
// room. Update the buffer size remaining.
//
if(ulSize != 0)
{
*pcBuf++ = (char)ulValue;
ulSize--;
}
//
// Update the conversion count.
//
iConvertCount++;
//
// This command has been handled.
//
break;
}
//
// Handle the %d command.
//
case 'd':
{
//
// Get the value from the varargs.
//
ulValue = va_arg(vaArgP, unsigned long);
//
// If the value is negative, make it positive and indicate
// that a minus sign is needed.
//
if((long)ulValue < 0)
{
//
// Make the value positive.
//
ulValue = -(long)ulValue;
//
// Indicate that the value is negative.
//
ulNeg = 1;
}
else
{
//
// Indicate that the value is positive so that a
// negative sign isn't inserted.
//
ulNeg = 0;
}
//
// Set the base to 10.
//
ulBase = 10;
//
// Convert the value to ASCII.
//
goto convert;
}
//
// Handle the %s command.
//
case 's':
{
//
// Get the string pointer from the varargs.
//
pcStr = va_arg(vaArgP, char *);
//
// Determine the length of the string.
//
for(ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++)
{
}
//
// Update the convert count to include any padding that
// should be necessary (regardless of whether we have space
// to write it or not).
//
if(ulCount > ulIdx)
{
iConvertCount += (ulCount - ulIdx);
}
//
// Copy the string to the output buffer. Only copy as much
// as will fit in the buffer. Update the output buffer
// pointer and the space remaining.
//
if(ulIdx > ulSize)
{
strncpy(pcBuf, pcStr, ulSize);
pcBuf += ulSize;
ulSize = 0;
}
else
{
strncpy(pcBuf, pcStr, ulIdx);
pcBuf += ulIdx;
ulSize -= ulIdx;
//
// Write any required padding spaces assuming there is
// still space in the buffer.
//
if(ulCount > ulIdx)
{
ulCount -= ulIdx;
if(ulCount > ulSize)
{
ulCount = ulSize;
}
ulSize =- ulCount;
while(ulCount--)
{
*pcBuf++ = ' ';
}
}
}
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -