allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (03/05/89)
Posting-number: Volume 6, Issue 42 Submitted-by: blarson%skat.usc.edu@oberon.usc.edu (Bob Larson) Archive-name: vsprintf.port [That, and a few other things.... ++bsa] Here is the portable vsprinf function I promised. Uunet had a problem with their comp-source-misc sumbission address, so this is a bit late, but it now includes vfprintf and vprintf. No makefile is included since this was developted on and for a non- unix system, (os9/68k) but it should be portable to almost anything with a working varargs and sprintf/fprintf. # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # vsprintf.doc # vsprintf.c # vfprintf.c # This archive created: Thu Feb 9 20:06:13 1989 # By: blarson cat << \SHAR_EOF > vsprintf.doc Portable vsprintf, vfprintf, and vprintf by Robert A. Larson <blarson@skat.usc.edu> Copyright 1989 Robert A. Larson. Distribution in any form is allowed as long as the author retains credit, changes are noted by their author and the copyright message remains intact. This program comes as-is with no warentee of fitness for any purpouse. Thanks to Doug Gwen, Chris Torek, and others who helped clarify the ansi printf specs. Please send any bug fixes and improvments to blarson@skat.usc.edu . The use of goto is NOT a bug. Feb 9, 1989 blarson First usenet release This code implements the vsprintf function, without relying on the existance of _doprint or other system specific code. Define NOVOID if void * is not a supported type. Two compile options are available for efficency: INTSPRINTF should be defined if sprintf is int and returns the number of chacters formated. LONGINT should be defined if sizeof(long) == sizeof(int) They only make the code smaller and faster, they need not be defined. UNSIGNEDSPECIAL should be defined if unsigned is treated differently than int in argument passing. If this is definded, and LONGINT is not, the compiler must support the type unsigned long. Most quirks and bugs of the available sprintf and fprintf fuction are duplicated, however * in the width and precision fields will work correctly even if sprintf does not support this, and the %n format will always work in vsprintf. %n and return count will work properly in vfprintf and vprintf only if fprintf returns the number of characters formatted. Bad format strings, or those with very long width and precision fields (including expanded * fields) will cause undesired results. SHAR_EOF cat << \SHAR_EOF > vsprintf.c /* Portable vsprintf by Robert A. Larson <blarson@skat.usc.edu> */ /* Copyright 1989 Robert A. Larson. * Distribution in any form is allowed as long as the author * retains credit, changes are noted by their author and the * copyright message remains intact. This program comes as-is * with no warentee of fitness for any purpouse. * * Thanks to Doug Gwen, Chris Torek, and others who helped clarify * the ansi printf specs. * * Please send any bug fixes and improvments to blarson@skat.usc.edu . * The use of goto is NOT a bug. */ /* Feb 7, 1989 blarson First usenet release */ /* This code implements the vsprintf function, without relying on * the existance of _doprint or other system specific code. * * Define NOVOID if void * is not a supported type. * * Two compile options are available for efficency: * INTSPRINTF should be defined if sprintf is int and returns * the number of chacters formated. * LONGINT should be defined if sizeof(long) == sizeof(int) * * They only make the code smaller and faster, they need not be * defined. * * UNSIGNEDSPECIAL should be defined if unsigned is treated differently * than int in argument passing. If this is definded, and LONGINT is not, * the compiler must support the type unsingned long. * * Most quirks and bugs of the available sprintf fuction are duplicated, * however * in the width and precision fields will work correctly * even if sprintf does not support this, as will the n format. * * Bad format strings, or those with very long width and precision * fields (including expanded * fields) will cause undesired results. */ #ifdef OSK /* os9/68k can take advantage of both */ #define LONGINT #define INTSPRINTF #endif /* This must be a typedef not a #define! */ #ifdef NOVOID typedef char *pointer; #else typedef void *pointer; #endif #ifdef INTSPRINTF #define Sprintf(string,format,arg) (sprintf((string),(format),(arg))) #else #define Sprintf(string,format,arg) (\ sprintf((string),(format),(arg)),\ strlen(string)\ ) #endif #ifdef __STDC__ #include <stdarg.h> #else #include <varargs.h> #endif typedef int *intp; int vsprintf(dest, format, args) char *dest; register char *format; va_list args; { register char *dp = dest; register char c; register char *tp; char tempfmt[64]; #ifndef LONGINT int longflag; #endif tempfmt[0] = '%'; while(c = *format++) { if(c=='%') { tp = &tempfmt[1]; #ifndef LONGINT longflag = 0; #endif continue_format: switch(c = *format++) { case 's': *tp++ = c; *tp = '\0'; dp += Sprintf(dp, tempfmt, va_arg(args, char *)); break; case 'u': case 'x': case 'o': case 'X': #ifdef UNSIGNEDSPECIAL *tp++ = c; *tp = '\0'; #ifndef LONGINT if(longflag) dp += Sprintf(dp, tempfmt, va_arg(args, unsigned long)); else #endif dp += Sprintf(dp, tempfmt, va_arg(args, unsigned)); break; #endif case 'd': case 'c': case 'i': *tp++ = c; *tp = '\0'; #ifndef LONGINT if(longflag) dp += Sprintf(dp, tempfmt, va_arg(args, long)); else #endif dp += Sprintf(dp, tempfmt, va_arg(args, int)); break; case 'f': case 'e': case 'E': case 'g': case 'G': *tp++ = c; *tp = '\0'; dp += Sprintf(dp, tempfmt, va_arg(args, double)); break; case 'p': *tp++ = c; *tp = '\0'; dp += Sprintf(dp, tempfmt, va_arg(args, pointer)); break; case '-': case '+': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': case ' ': case '#': case 'h': *tp++ = c; goto continue_format; case 'l': #ifndef LONGINT longflag = 1; *tp++ = c; #endif goto continue_format; case '*': tp += Sprintf(tp, "%d", va_arg(args, int)); goto continue_format; case 'n': *va_arg(args, intp) = dp - dest; break; case '%': default: *dp++ = c; break; } } else *dp++ = c; } *dp = '\0'; return dp - dest; } SHAR_EOF cat << \SHAR_EOF > vfprintf.c /* Portable vfprintf and vprintf by Robert A. Larson <blarson@skat.usc.edu> */ /* Copyright 1989 Robert A. Larson. * Distribution in any form is allowed as long as the author * retains credit, changes are noted by their author and the * copyright message remains intact. This program comes as-is * with no warentee of fitness for any purpouse. * * Thanks to Doug Gwen, Chris Torek, and others who helped clarify * the ansi printf specs. * * Please send any bug fixes and improvments to blarson@skat.usc.edu . * The use of goto is NOT a bug. */ /* Feb 9, 1989 blarson First usenet release */ /* This code implements the vfprintf function, without relying on * the existance of _doprint or other system specific code. * * Define NOVOID if void * is not a supported type. * * Two compile options are available for efficency: * INTSPRINTF should be defined if sprintf is int and returns * the number of chacters formated. * LONGINT should be defined if sizeof(long) == sizeof(int) * * They only make the code smaller and faster, they need not be * defined. * * UNSIGNEDSPECIAL should be defined if unsigned is treated differently * than int in argument passing. If this is definded, and LONGINT is not, * the compiler must support the type unsingned long. * * Most quirks and bugs of the available fprintf fuction are duplicated, * however * in the width and precision fields will work correctly * even if fprintf does not support this. The %n format and the return * count will only work if fprintf returns the number of characters * formatted. * * Bad format strings, or those with very long width and precision * fields (including expanded * fields) will cause undesired results. */ #ifdef OSK /* os9/68k can take advantage of both */ #define INTSPRINTF #define LONGINT #endif /* This must be a typedef not a #define! */ #ifdef NOVOID typedef char *pointer; #else typedef void *pointer; #endif #include <stdio.h> #ifdef INTSPRINTF #define Sprintf(string,format,arg) (sprintf((string),(format),(arg))) #else #define Sprintf(string,format,arg) (\ sprintf((string),(format),(arg)),\ strlen(string)\ ) #endif #ifdef __STDC__ #include <stdarg.h> #else #include <varargs.h> #endif typedef int *intp; int vfprintf(dest, format, args) FILE *dest; register char *format; va_list args; { register char c; register char *tp; register int count = 0; char tempfmt[64]; #ifndef LONGINT int longflag; #endif tempfmt[0] = '%'; while(c = *format++) { if(c=='%') { tp = &tempfmt[1]; #ifndef LONGINT longflag = 0; #endif continue_format: switch(c = *format++) { case 's': *tp++ = c; *tp = '\0'; count += fprintf(dest, tempfmt, va_arg(args, char *)); break; case 'u': case 'x': case 'o': case 'X': #ifdef UNSIGNEDSPECIAL *tp++ = c; *tp = '\0'; #ifndef LONGINT if(longflag) count += fprintf(dest, tempfmt, va_arg(args, unsigned long)); else #endif count += fprintf(dest, tempfmt, va_arg(args, unsigned)); break; #endif case 'd': case 'c': case 'i': *tp++ = c; *tp = '\0'; #ifndef LONGINT if(longflag) count += fprintf(dest, tempfmt, va_arg(args, long)); else #endif count += fprintf(dest, tempfmt, va_arg(args, int)); break; case 'f': case 'e': case 'E': case 'g': case 'G': *tp++ = c; *tp = '\0'; count += fprintf(dest, tempfmt, va_arg(args, double)); break; case 'p': *tp++ = c; *tp = '\0'; count += fprintf(dest, tempfmt, va_arg(args, pointer)); break; case '-': case '+': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': case ' ': case '#': case 'h': *tp++ = c; goto continue_format; case 'l': #ifndef LONGINT longflag = 1; *tp++ = c; #endif goto continue_format; case '*': tp += Sprintf(tp, "%d", va_arg(args, int)); goto continue_format; case 'n': *va_arg(args, intp) = count; break; case '%': default: putc(c, dest); count++; break; } } else { putc(c, dest); count++; } } return count; } vprintf(format, args) char *format; va_list args; { return vfprintf(stdout, format, args); } SHAR_EOF # End of shell archive exit 0 -- Bob Larson Arpa: Blarson@Ecla.Usc.Edu blarson@skat.usc.edu Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson Prime mailing list: info-prime-request%ais1@ecla.usc.edu oberon!ais1!info-prime-request