"Fossies" - the Fresh Open Source Software Archive 
Member "tin-2.6.2/src/plp_snprintf.c" (9 Dec 2022, 17057 Bytes) of package /linux/misc/tin-2.6.2.tar.xz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "plp_snprintf.c" see the
Fossies "Dox" file reference documentation.
1 /**************************************************************************
2 * LPRng IFHP Filter
3 * Copyright 1994-1999 Patrick Powell, San Diego, CA <papowell@astart.com>
4 **************************************************************************/
5
6 /*
7 * Overview:
8 *
9 * This version of snprintf was developed originally for printing
10 * on a motley collection of specialized hardware that had NO IO
11 * library. Due to contractual restrictions, a clean room implementation
12 * of the printf() code had to be developed.
13 *
14 * The method chosen for printf was to be as paranoid as possible,
15 * as these platforms had NO memory protection, and very small
16 * address spaces. This made it possible to try to print
17 * very long strings, i.e. - all of memory, very easily. To guard
18 * against this, all printing was done via a buffer, generous enough
19 * to hold strings, but small enough to protect against overruns,
20 * etc.
21 *
22 * Strangely enough, this proved to be of immense importance when
23 * SPRINTFing to a buffer on a stack... The rest, of course, is
24 * well known, as buffer overruns in the stack are a common way to
25 * do horrible things to operating systems, security, etc etc.
26 *
27 * This version of snprintf is VERY limited by modern standards.
28 *
29 * COPYRIGHT AND TERMS OF USE:
30 *
31 * You may use, copy, distribute, or otherwise incorporate this software
32 * and documentation into any product or other item, provided that
33 * the copyright in the documentation and source code as well as the
34 * source code generated constant strings in the object, executable
35 * or other code remain in place and are present in executable modules
36 * or objects.
37 *
38 * You may modify this code as appropriate to your usage; however the
39 * modified version must be identified by changing the various source
40 * and object code identification strings as is appropriately noted
41 * in the source code.
42 *
43 * The next include line is expected to work in conjunction with the
44 * GNU CONFIGURE utility. You should define the following macros
45 * appropriately:
46 *
47 * HAVE_STDARG_H - if the <stdargs.h> include file is available
48 * HAVE_VARARG_H - if the <varargs.h> include file is available
49 *
50 * HAVE_STRERROR - if the strerror() routine is available.
51 * If it is not available, then examine the lines containing
52 * the tests below. You may need to fiddle with HAVE_SYS_NERR
53 * and HAVE_SYS_NERR_DEF to make compilation work correctly.
54 * HAVE_SYS_NERR
55 * HAVE_SYS_NERR_DEF
56 *
57 * HAVE_QUAD_T - if the quad_t type is defined
58 * HAVE_LONG_LONG - if the long long type is defined
59 *
60 * If you are using the GNU configure (autoconf) facility, add the
61 * following line to the configure.in file, to force checking for the
62 * quad_t and long long data types:
63 *
64 * AC_CHECK_TYPE(quad_t,NONE)
65 *
66 * dnl test to see if long long is defined
67 *
68 * AC_MSG_CHECKING(checking for long long)
69 * AC_TRY_COMPILE([
70 * #include <sys/types.h>
71 * ],[long long x; x = 0],
72 * ac_cv_long_long=yes, ac_cv_long_long=no)
73 * AC_MSG_RESULT($ac_cv_long_long)
74 * if test $ac_cv_long_long = yes; then
75 * AC_DEFINE(HAVE_LONG_LONG)
76 * fi
77 *
78 *
79 * Add the following lines to the acconfig.h in the correct
80 * position.
81 *
82 * / * Define if quad_t is NOT present on the system * /
83 * #undef quad_t
84 *
85 * / * Define if long long is present on the system * /
86 * #undef HAVE_LONG_LONG
87 *
88 * When you run configure, if quad_t is NOT defined, the config.h
89 * file will have in it:
90 * #define quad_t NONE
91 *
92 * If it is defined, the config.h file will have
93 * / * #undef quad_t * /
94 *
95 * If long long is defined, you will have:
96 * #define HAVE_LONG_LONG
97 *
98 * This code is then used in the source code to enable quad quad
99 * and long long support.
100 *
101 */
102
103
104 #ifndef TIN_H
105 # include "tin.h"
106 #endif /* !TIN_H */
107
108 #if !defined(HAVE_SNPRINTF) && !defined(HAVE_VSNPRINTF)
109
110 # if !defined(PLP_SNPRINTF_H) && !defined(TIN_H)
111 # include "plp_snprintf.h"
112 # endif /* !PLP_SNPRINTF_H && !TIN_H */
113
114 /*
115 * KEEP THIS STRING - MODIFY AT THE END WITH YOUR REVISIONS
116 * i.e. - the LOCAL REVISIONS part is for your use
117 */
118
119 static const char *_id = "plp_snprintf V1999.02.20 Copyright Patrick Powell 1988-1999 <papowell@astart.com> \
120 $Id: plp_snprintf.c,v 1.4 1999/02/20 17:44:16 papowell Exp papowell $\
121 LOCAL REVISIONS: tin 1.9.5-01";
122
123 /* varargs declarations: */
124
125 #ifdef HAVE_STDARGS
126 # undef HAVE_STDARGS /* let's hope that works everywhere (mj) */
127 #endif /* HAVE_STDARGS */
128 #ifdef VA_LOCAL_DECL
129 # undef VA_LOCAL_DECL
130 #endif /* VA_LOCAL_DECL */
131 #ifdef VA_START
132 # undef VA_START
133 #endif /* VA_START */
134 #ifdef VA_SHIFT
135 # undef VA_SHIFT
136 #endif /* VA_SHIFT */
137 #ifdef VA_END
138 # undef VA_END
139 #endif /* VA_END */
140
141 #ifdef HAVE_STDARG_H
142 # include <stdarg.h>
143 # define HAVE_STDARGS /* let's hope that works everywhere (mj) */
144 # define VA_LOCAL_DECL va_list ap;
145 # define VA_START(f) va_start(ap, f)
146 # define VA_SHIFT(v,t) ; /* no-op for ANSI */
147 # define VA_END va_end(ap)
148 #else
149 # ifdef HAVE_VARARGS_H
150 # include <varargs.h>
151 # undef HAVE_STDARGS
152 # define VA_LOCAL_DECL va_list ap;
153 # define VA_START(f) va_start(ap) /* f is ignored! */
154 # define VA_SHIFT(v,t) v = va_arg(ap,t)
155 # define VA_END va_end(ap)
156 # else
157 XX ** NO VARARGS ** XX
158 # endif /* HAVE_VARARGS_H */
159 #endif /* HAVE_STDARG_H */
160
161 #if 0
162 /* the dreaded QUAD_T strikes again... */
163 #ifndef HAVE_QUAD_T
164 # if defined(quad_t) && qaud_t == NONE
165 # define HAVE_QUAD_T 0
166 # else
167 # define HAVE_QUAD_T 1
168 # endif /* quad_t && qaud_t== NONE */
169 #endif /* HAVE_QUAD_T */
170 #endif /* 0 */
171
172 #if defined(HAVE_QUAD_T) && !defined(HAVE_LONG_LONG)
173 ERROR you need long long
174 #endif
175 #ifdef HAVE_QUAD_T
176 /* suspender and belts on this one */
177 const union { quad_t t; long long v; } x;
178 #endif
179
180 union value {
181 #if defined(HAVE_QUAD_T) || defined(HAVE_LONG_LONG)
182 long long value;
183 #else
184 long value;
185 #endif
186 double dvalue;
187 };
188
189 #ifdef cval
190 # undef cval
191 #endif /* cval */
192 #define cval(s) (*((unsigned const char *)s))
193
194
195 static char *plp_Errormsg(int err);
196 static void plp_strcat(char *dest, const char *src);
197 static void dopr(char *buffer, const char *format, va_list args);
198 static void fmtstr(const char *value, int ljust, int len, int precision);
199 static void fmtnum(union value *value, int plp_base, int dosign, int ljust, int len, int zpad);
200 static void fmtdouble(int fmt, double value, int ljust, int len, int zpad, int precision);
201 static void dostr(const char *);
202 static void dopr_outch(int c);
203
204 static char *output;
205 static char *end;
206
207 int visible_control = 1;
208
209
210 int plp_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
211 {
212 str[0] = 0;
213 end = str+count-1;
214 dopr( str, fmt, args );
215 if( count != 0 )
216 end[0] = 0;
217 return(strlen(str));
218 }
219
220 /* VARARGS3 */
221 #ifdef HAVE_STDARGS
222 int plp_snprintf(char *str,size_t count,const char *fmt,...)
223 #else
224 int plp_snprintf(va_alist) va_dcl
225 #endif
226 {
227 #ifndef HAVE_STDARGS
228 char *str;
229 size_t count;
230 char *fmt;
231 #endif
232 VA_LOCAL_DECL
233
234 VA_START (fmt);
235 VA_SHIFT (str, char *);
236 VA_SHIFT (count, size_t );
237 VA_SHIFT (fmt, char *);
238 (void) plp_vsnprintf( str, count, fmt, ap);
239 VA_END;
240 return( strlen( str ) );
241 }
242
243 static void dopr( char *buffer, const char *format, va_list args )
244 {
245 int ch;
246 union value value;
247 int longflag = 0;
248 int quadflag = 0;
249 char *strvalue;
250 int ljust;
251 int len;
252 int zpad;
253 int precision;
254 int set_precision;
255 double dval;
256 int err = errno;
257 int plp_base = 0;
258 int signed_val = 0;
259
260 output = buffer;
261 while( (ch = *format++) ){
262 switch( ch ){
263 case '%':
264 longflag = quadflag =
265 ljust = len = zpad = plp_base = signed_val = 0;
266 precision = -1; set_precision = 0;
267 nextch:
268 ch = *format++;
269 switch( ch ){
270 case 0:
271 dostr( "**end of format**" );
272 return;
273 case '-': ljust = 1; goto nextch;
274 case '.': set_precision = 1; precision = 0; goto nextch;
275 case '*':
276 if( set_precision ){
277 precision = va_arg( args, int );
278 } else {
279 len = va_arg( args, int );
280 }
281 goto nextch;
282 case '0': /* set zero padding if len not set */
283 if(len==0 && set_precision == 0 ) zpad = '0';
284 /* FALLTHROUGH */
285 case '1': /* FALLTHROUGH */
286 case '2': /* FALLTHROUGH */
287 case '3': /* FALLTHROUGH */
288 case '4': /* FALLTHROUGH */
289 case '5': /* FALLTHROUGH */
290 case '6': /* FALLTHROUGH */
291 case '7': /* FALLTHROUGH */
292 case '8': /* FALLTHROUGH */
293 case '9':
294 if( set_precision ){
295 precision = precision*10 + ch - '0';
296 } else {
297 len = len*10 + ch - '0';
298 }
299 goto nextch;
300 case 'l': ++longflag; goto nextch;
301 case 'q': quadflag = 1; goto nextch;
302 case 'u': case 'U':
303 if( plp_base == 0 ){ plp_base = 10; signed_val = 0; }
304 /* FALLTHROUGH */
305 case 'o': case 'O':
306 if( plp_base == 0 ){ plp_base = 8; signed_val = 0; }
307 /* FALLTHROUGH */
308 case 'd': case 'D':
309 if( plp_base == 0 ){ plp_base = 10; signed_val = 1; }
310 /* FALLTHROUGH */
311 case 'x':
312 if( plp_base == 0 ){ plp_base = 16; signed_val = 0; }
313 /* FALLTHROUGH */
314 case 'X':
315 if( plp_base == 0 ){ plp_base = -16; signed_val = 0; }
316 if( quadflag || longflag > 1 ){
317 #if defined(HAVE_LONG_LONG)
318 if( signed_val ){
319 value.value = va_arg( args, long long );
320 } else {
321 value.value = va_arg( args, unsigned long long );
322 }
323 #else
324 if( signed_val ){
325 value.value = va_arg( args, long );
326 } else {
327 value.value = va_arg( args, unsigned long );
328 }
329 #endif
330 } else if( longflag ){
331 if( signed_val ){
332 value.value = va_arg( args, long );
333 } else {
334 value.value = va_arg( args, unsigned long );
335 }
336 } else {
337 if( signed_val ){
338 value.value = va_arg( args, int );
339 } else {
340 value.value = va_arg( args, unsigned int );
341 }
342 }
343 fmtnum( &value,plp_base,signed_val, ljust, len, zpad );
344 break;
345 case 's':
346 strvalue = va_arg( args, char *);
347 fmtstr(strvalue, ljust, len, precision);
348 break;
349 case 'c':
350 ch = va_arg( args, int );
351 { char b[2];
352 int vsb = visible_control;
353 b[0] = ch;
354 b[1] = 0;
355 visible_control = 0;
356 fmtstr(b, ljust, len, precision);
357 visible_control = vsb;
358 }
359 break;
360 case 'f': case 'g': case 'e':
361 dval = va_arg( args, double );
362 fmtdouble(ch, dval, ljust, len, zpad, precision);
363 break;
364 case 'm':
365 fmtstr(plp_Errormsg(err), ljust, len, precision);
366 break;
367 case '%': dopr_outch( ch ); continue;
368 default:
369 dostr( "???????" );
370 }
371 longflag = 0;
372 break;
373 default:
374 dopr_outch( ch );
375 break;
376 }
377 }
378 *output = 0;
379 }
380
381 /*
382 * Format '%[-]len[.precision]s'
383 * - = left justify (ljust)
384 * len = minimum length
385 * precision = numbers of chars in string to use
386 */
387 static void
388 fmtstr(const char *value, int ljust, int len, int precision)
389 {
390 int padlen, slen, i, c; /* amount to pad */
391
392 if( value == 0 ){
393 value = "<NULL>";
394 }
395 if( precision > 0 ){
396 slen = precision;
397 } else {
398 /* cheap slen so you do not have library call */
399 for( slen = i = 0; (c=cval(value+i)); ++i ){
400 if( visible_control && iscntrl( c ) && !isspace(c) ){
401 ++slen;
402 }
403 ++slen;
404 }
405 }
406 padlen = len - slen;
407 if( padlen < 0 ) padlen = 0;
408 if( ljust ) padlen = -padlen;
409 while( padlen > 0 ) {
410 dopr_outch( ' ' );
411 --padlen;
412 }
413 /* output characters */
414 for( i = 0; (c = cval(value+i)); ++i ){
415 if( visible_control && iscntrl( c ) && !isspace( c ) ){
416 dopr_outch('^');
417 c = ('@' | (c & 0x1F));
418 }
419 dopr_outch(c);
420 }
421 while( padlen < 0 ) {
422 dopr_outch( ' ' );
423 ++padlen;
424 }
425 }
426
427 static void
428 fmtnum( union value *value, int plp_base, int dosign, int ljust,
429 int len, int zpad )
430 {
431 int signvalue = 0;
432 #ifdef HAVE_LONG_LONG
433 unsigned long long uvalue;
434 #else
435 unsigned long uvalue;
436 #endif /* HAVE_LONG_LONG */
437 char convert[64];
438 int place = 0;
439 int padlen = 0; /* amount to pad */
440 int caps = 0;
441
442 /* fprintf(stderr,"value 0x%x, plp_base %d, dosign %d, ljust %d, len %d, zpad %d\n",
443 value, plp_base, dosign, ljust, len, zpad );/ **/
444 uvalue = value->value;
445 if( dosign ){
446 if( value->value < 0 ) {
447 signvalue = '-';
448 uvalue = -value->value;
449 }
450 }
451 if( plp_base < 0 ){
452 caps = 1;
453 plp_base = -plp_base;
454 }
455 do{
456 convert[place++] =
457 (caps? "0123456789ABCDEF":"0123456789abcdef")
458 [uvalue % (unsigned)plp_base ];
459 uvalue = (uvalue / (unsigned)plp_base );
460 }while(uvalue);
461 convert[place] = 0;
462 padlen = len - place;
463 if( padlen < 0 ) padlen = 0;
464 if( ljust ) padlen = -padlen;
465 /* fprintf( stderr, "str '%s', place %d, sign %c, padlen %d\n",
466 convert,place,signvalue,padlen); / **/
467 if( zpad && padlen > 0 ){
468 if( signvalue ){
469 dopr_outch( signvalue );
470 --padlen;
471 signvalue = 0;
472 }
473 while( padlen > 0 ){
474 dopr_outch( zpad );
475 --padlen;
476 }
477 }
478 while( padlen > 0 ) {
479 dopr_outch( ' ' );
480 --padlen;
481 }
482 if( signvalue ) dopr_outch( signvalue );
483 while( place > 0 ) dopr_outch( convert[--place] );
484 while( padlen < 0 ){
485 dopr_outch( ' ' );
486 ++padlen;
487 }
488 }
489
490 static void
491 plp_strcat(char *dest, const char *src )
492 {
493 if( dest && src ){
494 dest += strlen(dest);
495 strcpy(dest,src);
496 }
497 }
498
499 static void
500 fmtdouble( int fmt, double value, int ljust, int len, int zpad, int precision )
501 {
502 char convert[128];
503 char fmts[128];
504 int l;
505
506 if( len == 0 )
507 len = 10;
508 if( len > (int) (sizeof(convert) - 20) )
509 len = sizeof(convert) - 20;
510 if( precision > (int) sizeof(convert) - 20 )
511 precision = sizeof(convert) - 20;
512 if( precision > len )
513 precision = len;
514 strcpy( fmts, "%" );
515 if( ljust )
516 plp_strcat(fmts, "-" );
517 if( zpad )
518 plp_strcat(fmts, "0" );
519 if( len )
520 sprintf( fmts+strlen(fmts), "%d", len );
521 if( precision > 0 )
522 sprintf( fmts+strlen(fmts), ".%d", precision );
523 l = strlen( fmts );
524 fmts[l] = fmt;
525 fmts[l+1] = 0;
526 /* this is easier than trying to do the portable dtostr */
527 sprintf( convert, fmts, value );
528 dostr( convert );
529 }
530
531 static void dostr( const char *str )
532 {
533 while(*str) dopr_outch(*str++);
534 }
535
536 static void dopr_outch( int c )
537 {
538 if( end == 0 || output < end ){
539 *output++ = c;
540 }
541 }
542
543
544 /****************************************************************************
545 * static char *plp_errormsg( int err )
546 * returns a printable form of the
547 * errormessage corresponding to the valie of err.
548 * This is the poor man's version of sperror(), not available on all systems
549 * Patrick Powell Tue Apr 11 08:05:05 PDT 1995
550 ****************************************************************************/
551 /****************************************************************************/
552 #if !defined(HAVE_STRERROR)
553
554 # if defined(HAVE_SYS_NERR)
555 # if !defined(HAVE_SYS_NERR_DEF)
556 extern int sys_nerr;
557 # endif
558 # define num_errors (sys_nerr)
559 # else
560 # define num_errors (-1) /* always use "errno=%d" */
561 # endif
562
563 # if defined(HAVE_SYS_ERRLIST)
564 # if !defined(HAVE_SYS_ERRLIST_DEF)
565 extern const char *const sys_errlist[];
566 # endif
567 # else
568 # undef num_errors
569 # define num_errors (-1) /* always use "errno=%d" */
570 # endif
571
572 #endif
573
574 static char * plp_Errormsg ( int err )
575 {
576 char *cp;
577
578 #if defined(HAVE_STRERROR)
579 cp = (void *)strerror(err);
580 #else
581 # if defined(HAVE_SYS_ERRLIST)
582 if (err >= 0 && err < num_errors) {
583 cp = (void *)sys_errlist[err];
584 } else
585 # endif
586 {
587 static char msgbuf[32]; /* holds "errno=%d". */
588 /* SAFE use of sprintf */
589 (void) sprintf(msgbuf, "errno=%d", err);
590 cp = msgbuf;
591 }
592 #endif
593 return (cp);
594 }
595
596 #if defined(TEST)
597 #include <stdio.h>
598 int main( void )
599 {
600 char buffer[128];
601 char *t;
602 char *test1 = "01234";
603 errno = 1;
604 plp_snprintf( buffer, sizeof(buffer), (t="errno '%m'")); printf( "%s = '%s'\n", t, buffer );
605 plp_snprintf( buffer, sizeof(buffer), (t = "%s"), test1 ); printf( "%s = '%s'\n", t, buffer );
606 plp_snprintf( buffer, sizeof(buffer), (t = "%12s"), test1 ); printf( "%s = '%s'\n", t, buffer );
607 plp_snprintf( buffer, sizeof(buffer), (t = "%-12s"), test1 ); printf( "%s = '%s'\n", t, buffer );
608 plp_snprintf( buffer, sizeof(buffer), (t = "%12.2s"), test1 ); printf( "%s = '%s'\n", t, buffer );
609 plp_snprintf( buffer, sizeof(buffer), (t = "%-12.2s"), test1 ); printf( "%s = '%s'\n", t, buffer );
610 plp_snprintf( buffer, sizeof(buffer), (t = "%g"), 1.25 ); printf( "%s = '%s'\n", t, buffer );
611 plp_snprintf( buffer, sizeof(buffer), (t = "%g"), 1.2345 ); printf( "%s = '%s'\n", t, buffer );
612 plp_snprintf( buffer, sizeof(buffer), (t = "%12g"), 1.25 ); printf( "%s = '%s'\n", t, buffer );
613 plp_snprintf( buffer, sizeof(buffer), (t = "%12.2g"), 1.25 ); printf( "%s = '%s'\n", t, buffer );
614 plp_snprintf( buffer, sizeof(buffer), (t = "%0*d"), 6, 1 ); printf( "%s = '%s'\n", t, buffer );
615 #if defined(HAVE_LONG_LONG)
616 plp_snprintf( buffer, sizeof(buffer), (t = "%llx"), 1, 2, 3, 4 ); printf( "%s = '%s'\n", t, buffer );
617 plp_snprintf( buffer, sizeof(buffer), (t = "%llx"), (long long)1, (long long)2 ); printf( "%s = '%s'\n", t, buffer );
618 plp_snprintf( buffer, sizeof(buffer), (t = "%qx"), 1, 2, 3, 4 ); printf( "%s = '%s'\n", t, buffer );
619 plp_snprintf( buffer, sizeof(buffer), (t = "%qx"), (quad_t)1, (quad_t)2 ); printf( "%s = '%s'\n", t, buffer );
620 #endif
621 return(0);
622 }
623 #endif
624 #endif /* !HAVE_SNPRINTF && !HAVE_VSNPRINTF */