I couldn't figure out how to get your email, so I will just attach
it here....Now that I pasted it, its a mess. If you can't resolve
the linewrap mess, just send me your email address.
/********************************************************************
**********
Filename: tprintf.h
Description: The following function is a limited version of
sprintf(). It is
useful for applications where memory
is limited or code size
is an issue.
*********************************************************************
**********/
#ifndef TPRINTF_H
#define TPRINTF_H
extern "C" void tprintf(INT8S* buf, const INT8S* format, ...);
#endif
/******************************* End of
file***********************************/
/********************************************************************
**********
Filename: tprintf.cpp
Description: The following function is a limited version of
sprintf(). It is
useful for applications where memory
is limited or code size
is an issue.
*********************************************************************
**********/
/////////////////////////////////////////////////////////////////////
//////////
// includes
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include "Typedefs.h"
/////////////////////////////////////////////////////////////////////
//////////
// defines
/////////////////////////////////////////////////////////////////////
//////////
// Static's
/********************************************************************
**********
Name: numToAscii()
Description: The following function converts an integer to its
ASCII
representation in a given numeric
base.
Input: char* buf: Preallocated storage to place the
ASCII representation
unsigned long num: The number to be
converted to ASCII
int base: The number base to
represent the number.
Output: None
*********************************************************************
**********/
extern "C" void numToAscii(INT8S* buf, INT32U num, INT32S base) {
static INT8S digits[] = "0123456789ABCDEF";
INT32U temp;
if(num == 0L){
// If the number is 0, just stuf a "0" into the
buffer
buf[0] = '0';
buf[1] = '\0';
}
else{
// Figure out the length necessary of the ASCII
string representing
// the number
for(temp = num; temp > 0; temp /= base)
buf++;
// Mark the spot that will be the end of the string
*buf = '\0';
// Generate ASCII representation
for(temp = num; temp > 0; temp /= base)
*--buf = digits[temp % base];
}
}
/********************************************************************
**********
Name: tprintf()
Description: The following function is a limited version of
sprintf(). It is
useful for applications where memory
is limited or code size
is an issue. The syntax implements
the sprintf() standard argument
passing. A conversion specification
looks like:
% {flags} {field_width}
{length_modifier} conversion
where flags=
'-': Left justify field
'0': Zero padding to
field width, for d, l, h, and X
where field_width=
Number of characters to be
printed in the field. Field width
will be padded with space if
needed. If given as '*', the
next argument should be an
integer holding the field width.
where length_modifier=
h: Used before d or X
conversions to denote a short int
l: Used before d or X
conversions to denote a long int
where conversion=
d: Write signed decimal
integer value
X: Write an unsigned
hexadecimal (0-9, ABC...) integer value
c: Write a single character
s: Write a string
Input: char* buf: Pointer to a preallocated buffer
to store formatted
output
const char* format: The printf style
format string reduced to
the above control fields
...: Variable length argument list
Output: None
*********************************************************************
**********/
extern "C" void tprintf(INT8S* buf, const INT8S* format, ...) {
// Points to each unnamed argument in turn
va_list argPtr;
// Value of the pad string
INT32S pad;
INT32S clip;
// Conversion of ASCII to long
INT32S longVal;
INT8S* src;
INT8S* dst;
// Character used to pad a field appropriately given a width
argument
INT8S padChar = ' ';
// Is the format requesting a zero pad?
BOOL reqZeroPad = FALSE;
// Make argPtr point to the first unnamed argument
va_start(argPtr, format);
while(*format) {
// Loop through the entire format string
if(*format != '%'){
// If not the start of a conversion
specification, copy the character
// literally
*buf++ = *format++;
}
else{
// Found the start of a conversion
specification, increment past the
// "%" and get the field width value
format++;
if(*format == '*'){
// A width specification, an 'int'
argument from the argument
// list supplies the value
pad = va_arg(argPtr, int);
// Increment past the '*'
format++;
}
else{
if(*format == '-' || (*format >= '0'
&& *format <= '9')){
// A width specification
controlling the minimum number of
// characters printed. The '-
' specifies left justification.
pad = atoi(format);
// A leading zero indicates
the pad character should be a
// '0' instead of a space
if(*format == '0')
reqZeroPad = TRUE;
do{
// Increment past
the width specification
format++;
}
while((*format >= '0')&&
(*format <= '9'));
}
else
// No width value was
specified
pad = 0;
}
// Handle the type
switch(*format++){
case 'c':
// Write a single character.
Note: `char's are always widened
// when they appear in
variable or unknown argument positions.
// Obtain a widened char and
narrow it.
buf[0] = (char)(va_arg
(argPtr, INT32U));
buf[1] = '\0';
break;
case 's':
// Write a string
src = va_arg(argPtr, char*);
strcpy(buf, src);
break;
case 'l':
// Write a signed decimal
long integer value
// Skip the 'd' in '%ld'
format++;
// Pop the argument off teh
list
longVal = va_arg(argPtr,
long);
dst = buf;
if(longVal<0){
// Negative number
*dst++ = '-';
longVal = -longVal;
}
// Convert number to ASCII
representation
numToAscii(dst, longVal, 10);
// Determine pad character
if(reqZeroPad)
padChar = '0';
break;
case 'h':
// Write a signed short
integer value
// Skip the 'd' in '%ld'
format++;
// Pop the argument off teh
list
longVal = va_arg(argPtr,
INT32U);
dst = buf;
if(longVal<0){
// Negative number
*dst++ = '-';
longVal = -longVal;
}
// Convert number to ASCII
representation
numToAscii(dst, longVal, 10);
// Determine pad character
if(reqZeroPad)
padChar = '0';
break;
case 'X':
// Write an unsigned
hexidecimal (0-9, ABC...) integer value
longVal = (long)va_arg
(argPtr, int);
// Convert number to ASCII
representation
numToAscii(buf, longVal, 16);
// Determine pad character
if(reqZeroPad)
padChar = '0';
break;
case 'd':
// Write a signed decimal
integer value
longVal = (long)va_arg
(argPtr, int);
dst = buf;
if(longVal<0){
// Negative number
*dst++ = '-';
longVal = -longVal;
}
// Convert number to ASCII
representation
numToAscii(dst, longVal, 10);
break;
default:
buf[0] = format[-1];
buf[1] = '\0';
break;
};
// Fix the padding if the value is too short
clip = strlen(buf);
if(pad < 0){
// Add spaces after the value
pad = -pad - clip;
for(buf += clip; pad > 0; pad++)
*buf++ = padChar;
buf = '\0';
}
else{
// Add spaces before the value
pad -= clip;
if(pad > 0){
// Width specification is
greater than string length, therefore
// pad appropriatly
// Point to the end of the
destination string
src = buf + clip;
// Point to the end of the
unpadded destination string
dst = src + pad;
// Terminate this field
*dst = '\0';
while(src > buf)
// Right justify the
string within the width specification
*--dst = *--src;
while(dst > buf)
// Fill with spaces
to the left
*--dst = padChar;
}
buf += strlen(buf);
}
}
}
// Mark the end of the output strin
*buf = '\0';
// Clean up the variable argument list
va_end(argPtr);
}
/******************************* End of
file***********************************/
--- In lpc2000@yahoogroups.com, "gene_klein2000" <gene_klein@h...>
wrote:
>
> Hoi Tim,
>
> It would be great if you wanna mail it to me.
>
> THANKS,
>
> Gene.
>
> --- In lpc2000@yahoogroups.com, "tah2k" <tah2k@y...> wrote:
> >
> > Hi Gene-
> >
> > I ran into the same problem a few years ago when I was trying to
use
> > sprintf in my boot block. It turns out that most of the code is
> > related to floating point conversions. I wrote my own 'tprintf'
('t'
> > for Tim) that does everything except floating point and it is
very
> > tight and small. I can email it to you if youlike.
> >
> > -Tim
> >
> > --- In lpc2000@yahoogroups.com, "gene_klein2000"
<gene_klein@h...>
> > wrote:
> > >
> > > Hi,
> > >
> > > I hope someone will help me with the next problem.
> > >
> > >
> > > When I'm using vsprintf the code generated by th compiler
> > > grows with about 30kB.
> > > Can anyone explain what I can to keep the code small and
> > > still be using th vsprintf.
> > >
> > > I'm using the gnuarm compiler.
> > >
> > >
> > > Thanks,
> > >
> > > GeneMessage
Re: large code generation with vsprintf
2005-01-28 by tah2k
Attachments
- No local attachments were found for this message.