Define LSOF_CC to system CC
[platform/upstream/lsof.git] / lib / snpf.c
1 /*
2  * snpf.c -- snprintf() empulation functions for lsof library
3  *
4  * V. Abell
5  * Purdue University Computing Center
6  */
7
8 /*
9  * Copyright 2000 Purdue Research Foundation, West Lafayette, Indiana
10  * 47907.  All rights reserved.
11  *
12  * Written by Victor A. Abell
13  *
14  * This software is not subject to any license of the American Telephone
15  * and Telegraph Company or the Regents of the University of California.
16  *
17  * This software has been adapted from snprintf.c in sendmail 8.9.3.  It
18  * is subject to the sendmail copyright statements listed below, and the
19  * sendmail licensing terms stated in the sendmail LICENSE file comment
20  * section of this file.
21  *
22  * Permission is granted to anyone to use this software for any purpose on
23  * any computer system, and to alter it and redistribute it freely, subject
24  * to the following restrictions:
25  *
26  * 1. Neither the authors nor Purdue University are responsible for any
27  *    consequences of the use of this software.
28  *
29  * 2. The origin of this software must not be misrepresented, either by
30  *    explicit claim or by omission.  Credit to the authors and Purdue
31  *    University must appear in documentation and sources.
32  *
33  * 3. Altered versions must be plainly marked as such, and must not be
34  *    misrepresented as being the original software.
35  *
36  * 4. This notice may not be removed or altered.
37  */
38
39 #include "../machine.h"
40
41 #ifdef  USE_LIB_SNPF
42
43 /*
44  * Sendmail copyright statements:
45  *
46  * Copyright (c) 1998 Sendmail, Inc.  All rights reserved.
47  * Copyright (c) 1997 Eric P. Allman.  All rights reserved.
48  * Copyright (c) 1988, 1993
49  *      The Regents of the University of California.  All rights reserved.
50  *
51  * By using this file, you agree to the terms and conditions set
52  * forth in the LICENSE file which can be found at the top level of
53  * the sendmail distribution.
54  *
55  * The LICENSE file may be found in the following comment section.
56  */
57
58
59 /*
60  * Begin endmail LICENSE file.
61
62                              SENDMAIL LICENSE
63
64 The following license terms and conditions apply, unless a different
65 license is obtained from Sendmail, Inc., 1401 Park Avenue, Emeryville, CA
66 94608, or by electronic mail at license@sendmail.com.
67
68 License Terms:
69
70 Use, Modification and Redistribution (including distribution of any
71 modified or derived work) in source and binary forms is permitted only if
72 each of the following conditions is met:
73
74 1. Redistributions qualify as "freeware" or "Open Source Software" under
75    one of the following terms:
76
77    (a) Redistributions are made at no charge beyond the reasonable cost of
78        materials and delivery.
79
80    (b) Redistributions are accompanied by a copy of the Source Code or by an
81        irrevocable offer to provide a copy of the Source Code for up to three
82        years at the cost of materials and delivery.  Such redistributions
83        must allow further use, modification, and redistribution of the Source
84        Code under substantially the same terms as this license.  For the
85        purposes of redistribution "Source Code" means the complete source
86        code of sendmail including all modifications.
87
88    Other forms of redistribution are allowed only under a separate royalty-
89    free agreement permitting such redistribution subject to standard
90    commercial terms and conditions.  A copy of such agreement may be
91    obtained from Sendmail, Inc. at the above address.
92
93 2. Redistributions of source code must retain the copyright notices as they
94    appear in each source code file, these license terms, and the
95    disclaimer/limitation of liability set forth as paragraph 6 below.
96
97 3. Redistributions in binary form must reproduce the Copyright Notice,
98    these license terms, and the disclaimer/limitation of liability set
99    forth as paragraph 6 below, in the documentation and/or other materials
100    provided with the distribution.  For the purposes of binary distribution
101    the "Copyright Notice" refers to the following language:
102    "Copyright (c) 1998 Sendmail, Inc.  All rights reserved."
103
104 4. Neither the name of Sendmail, Inc. nor the University of California nor
105    the names of their contributors may be used to endorse or promote
106    products derived from this software without specific prior written
107    permission.  The name "sendmail" is a trademark of Sendmail, Inc.
108
109 5. All redistributions must comply with the conditions imposed by the
110    University of California on certain embedded code, whose copyright
111    notice and conditions for redistribution are as follows:
112
113    (a) Copyright (c) 1988, 1993 The Regents of the University of
114        California.  All rights reserved.
115
116    (b) Redistribution and use in source and binary forms, with or without
117        modification, are permitted provided that the following conditions
118        are met:
119
120       (i)   Redistributions of source code must retain the above copyright
121             notice, this list of conditions and the following disclaimer.
122
123       (ii)  Redistributions in binary form must reproduce the above
124             copyright notice, this list of conditions and the following
125             disclaimer in the documentation and/or other materials provided
126             with the distribution.
127
128       (iii) All advertising materials mentioning features or use of this
129             software must display the following acknowledgement:  "This
130             product includes software developed by the University of
131             California, Berkeley and its contributors."
132
133       (iv)  Neither the name of the University nor the names of its
134             contributors may be used to endorse or promote products derived
135             from this software without specific prior written permission.
136
137 6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY
138    SENDMAIL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
139    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
140    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
141    NO EVENT SHALL SENDMAIL, INC., THE REGENTS OF THE UNIVERSITY OF
142    CALIFORNIA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
143    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
144    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
145    USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
146    ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
147    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
148    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
149
150 (Version 8.6, last updated 6/24/1998)
151
152  * End endmail LICENSE file.
153  */
154
155
156 /*
157  * If "ll" format support is not possible -- e.g., the long long type isn't
158  * supported -- define HAS_NO_LONG_LONG.
159  */
160
161 # ifndef lint
162 static char copyright[] =
163 "@(#) Copyright 2000 Purdue Research Foundation.\nAll rights reserved.\n";
164 # endif /* !defined(lint) */
165
166 #include <varargs.h>
167
168 #if     defined(__STDC__)
169 #define _PROTOTYPE(function, params)    function params
170 #else   /* !defined(__STDC__) */
171 #define _PROTOTYPE(function, params)    function()
172 #endif /* defined(__STDC__) */
173
174
175 /*
176 **  SNPRINTF, VSNPRINT -- counted versions of printf
177 **
178 **      These versions have been grabbed off the net.  They have been
179 **      cleaned up to compile properly and support for .precision and
180 **      %lx has been added.
181 */
182
183 /**************************************************************
184  * Original:
185  * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
186  * A bombproof version of doprnt (dopr) included.
187  * Sigh.  This sort of thing is always nasty do deal with.  Note that
188  * the version here does not include floating point...
189  *
190  * snprintf() is used instead of sprintf() as it does limit checks
191  * for string length.  This covers a nasty loophole.
192  *
193  * The other functions are there to prevent NULL pointers from
194  * causing nast effects.
195  **************************************************************/
196
197 /*static char _id[] = "$Id: snpf.c,v 1.5 2008/10/21 16:13:23 abe Exp $";*/
198
199
200 /*
201  * Local function prototypes
202  */
203
204 _PROTOTYPE(static void dopr,(char *bp, char *ep, char *fmt, va_list args));
205 _PROTOTYPE(static void dopr_outch,(char **bp, char *ep, int c));
206 _PROTOTYPE(static void dostr,(char **bp, char *ep, char *str, int));
207
208 # if    !defined(HAS_NO_LONG_LONG)
209 _PROTOTYPE(static void fmtllnum,(char **bp, char *ep, long long value,
210                                  int base, int dosign, int ljust, int len,
211                                  int zpad));
212 # endif /* !defined(HAS_NO_LONG_LONG) */
213
214 _PROTOTYPE(static void fmtnum,(char **bp, char *ep, long value, int base,
215                                int dosign, int ljust, int len, int zpad));
216 _PROTOTYPE(static void fmtstr,(char **bp, char *ep, char *value, int ljust,
217                                int len, int zpad,
218                                int maxwidth));
219
220
221 /*
222  * Local variables
223  */
224
225 static int Length;
226
227
228 /*
229  * snpf() -- count-controlled sprintf()
230  */
231
232 int
233 snpf(va_alist)
234         va_dcl                          /* requires at least three arguments:
235                                          *   bp =  receiving buffer pointer
236                                          *   ct =  length of buffer
237                                          *   fmt = format string
238                                          */
239 {
240         va_list args;
241         char *bp, *fmt;
242         int ct, len;
243
244         va_start(args);
245         bp = va_arg(args, char *);
246         ct = va_arg(args, int);
247         fmt = va_arg(args, char *);
248         len = vsnpf(bp, ct, fmt, args);
249         va_end(args);
250         return(len);
251 }
252
253
254 /*
255  * vsnpf() -- count-controlled vsprintf()
256  */
257
258 int
259 vsnpf(str, count, fmt, args)
260         char *str;                      /* result buffer */
261         int count;                      /* size of buffer */
262         char *fmt;                      /* format */
263         va_list args;                   /* variable length argument list */
264 {
265         char *ep = str + count - 1;
266
267         *str = '\0';
268         (void) dopr(str, ep, fmt, args);
269         if (count > 0)
270             *ep = '\0';
271         return(Length);
272 }
273
274
275 /*
276  * dopr() -- poor man's version of doprintf
277  */
278
279
280 static void
281 dopr(bp, ep, fmt, args)
282         char *bp;                       /* buffer start */
283         char *ep;                       /* buffer end (start + length - 1) */
284         char *fmt;                      /* format */
285         va_list args;                   /* variable length argument list */
286 {
287         int ch;
288         char ebuf[64];
289         int ebufl = (int)(sizeof(ebuf) - 1);
290         long value;
291         int longflag  = 0;
292         int longlongflag  = 0;
293         int pointflag = 0;
294         int maxwidth  = 0;
295         char *strvalue;
296         int ljust;
297         int len;
298         int zpad;
299         int zxflag = 0;
300
301 # if    !defined(HAS_NO_LONG_LONG)
302         long long llvalue;
303 # endif /* !defined(HAS_NO_LONG_LONG) */
304
305         Length = 0;
306         while((ch = *fmt++)) {
307             switch (ch) {
308             case '%':
309                 ljust = len = zpad = zxflag = maxwidth = 0;
310                 longflag = longlongflag = pointflag = 0;
311
312 nextch:
313
314                 ch = *fmt++;
315                 switch (ch) {
316                 case '\0':
317                     dostr(&bp, ep, "**end of format**" , 0);
318                     return;
319                 case '-':
320                     ljust = 1;
321                     goto nextch;
322                 case '0': /* set zero padding if len not set */
323                     if ((len == 0) && !pointflag)
324                         zpad = '0';
325                 case '1':
326                 case '2':
327                 case '3':
328                 case '4':
329                 case '5':
330                 case '6':
331                 case '7':
332                 case '8':
333                 case '9':
334                     if (pointflag)
335                         maxwidth = (maxwidth * 10) + (int)(ch - '0');
336                     else
337                          len = (len * 10) + (int)(ch - '0');
338                     goto nextch;
339                 case '*': 
340                    if (pointflag)
341                         maxwidth = va_arg(args, int);
342                     else
343                         len = va_arg(args, int);
344                     goto nextch;
345                 case '#':
346                     zxflag = 1;
347                     goto nextch;
348                 case '.':
349                     pointflag = 1;
350                     goto nextch;
351                 case 'l':
352                     if (longflag) {
353                         longflag = 0;
354                         longlongflag = 1;
355                         goto nextch;
356                     }
357                     longflag = 1;
358                     goto nextch;
359                 case 'u':
360                 case 'U':
361                     if (longlongflag) {
362
363 # if    !defined(HAS_NO_LONG_LONG)
364                         llvalue = va_arg(args, long long);
365                         (void) fmtllnum(&bp,ep,llvalue,10,0,ljust,len,zpad);
366 # else  /* defined(HAS_NO_LONG_LONG) */
367                         (void) strncpy(ebuf, "ll is unsupported", ebufl);
368                         ebuf[(int)ebufl] = '\0';
369                         (void) dostr(&bp, ep, ebuf, 0);
370 # endif /* !defined(HAS_NO_LONG_LONG) */
371
372                         break;
373                     }
374                     if (longflag)
375                         value = va_arg(args, long);
376                     else
377                         value = va_arg(args, int);
378                     (void) fmtnum(&bp, ep, value, 10,0, ljust, len, zpad);
379                     break;
380                 case 'o':
381                 case 'O':
382                     if (longlongflag) {
383
384 # if    !defined(HAS_NO_LONG_LONG)
385                         llvalue = va_arg(args, long long);
386                         (void) fmtllnum(&bp,ep,llvalue,8,0,ljust,len,zpad);
387 # else  /* defined(HAS_NO_LONG_LONG) */
388                         (void) strncpy(ebuf, "ll is unsupported", ebufl);
389                         ebuf[(int)ebufl] = '\0';
390                         (void) dostr(&bp, ep, ebuf, 0);
391 # endif /* !defined(HAS_NO_LONG_LONG) */
392
393                         break;
394                     }
395                     if (longflag)
396                         value = va_arg(args, long);
397                     else
398                         value = va_arg(args, int);
399                     (void) fmtnum(&bp, ep, value, 8,0, ljust, len, zpad);
400                     break;
401                 case 'd':
402                 case 'D':
403                     if (longlongflag) {
404
405 # if    !defined(HAS_NO_LONG_LONG)
406                         llvalue = va_arg(args, long long);
407                         (void) fmtllnum(&bp,ep,llvalue,10,1,ljust,len,zpad);
408 # else  /* defined(HAS_NO_LONG_LONG) */
409                         (void) strncpy(ebuf, "ll is unsupported", ebufl);
410                         ebuf[(int)ebufl] = '\0';
411                         (void) dostr(&bp, ep, ebuf, 0);
412 # endif /* !defined(HAS_NO_LONG_LONG) */
413
414                         break;
415                     }
416                     if (longflag)
417                         value = va_arg(args, long);
418                     else
419                         value = va_arg(args, int);
420                     (void) fmtnum(&bp, ep, value, 10,1, ljust, len, zpad);
421                     break;
422                 case 'x':
423                     if (longlongflag) {
424
425 # if    !defined(HAS_NO_LONG_LONG)
426                         llvalue = va_arg(args, long long);
427                         if (zxflag && llvalue) {
428                             (void) dostr(&bp, ep, "0x", 0);
429                             if (len >= 2)
430                                 len -= 2;
431                         }
432                         (void) fmtllnum(&bp,ep,llvalue,16,0,ljust,len,zpad);
433 # else  /* defined(HAS_NO_LONG_LONG) */
434                         (void) strncpy(ebuf, "ll is unsupported", ebufl);
435                         ebuf[(int)ebufl] = '\0';
436                         (void) dostr(&bp, ep, ebuf, 0);
437 # endif /* !defined(HAS_NO_LONG_LONG) */
438
439                         break;
440                     }
441                     if (longflag)
442                         value = va_arg(args, long);
443                     else
444                         value = va_arg(args, int);
445                     if (zxflag && value) {
446                         (void) dostr(&bp, ep, "0x", 0);
447                         if (len >= 2)
448                             len -= 2;
449                     }
450                     (void) fmtnum(&bp, ep, value, 16,0, ljust, len, zpad);
451                     break;
452                 case 'X':
453                     if (longlongflag) {
454
455 # if    !defined(HAS_NO_LONG_LONG)
456                         llvalue = va_arg(args, long long);
457                         if (zxflag && llvalue) {
458                             (void) dostr(&bp, ep, "0x", 0);
459                             if (len >= 2)
460                                 len -= 2;
461                         }
462                         (void) fmtllnum(&bp,ep,llvalue,-16,0,ljust,len,zpad);
463 # else  /* defined(HAS_NO_LONG_LONG) */
464                         (void) strncpy(ebuf, "ll is unsupported", ebufl);
465                         ebuf[(int)ebufl] = '\0';
466                         (void) dostr(&bp, ep, ebuf, 0);
467 # endif /* !defined(HAS_NO_LONG_LONG) */
468
469                         break;
470                     }
471                     if (longflag)
472                         value = va_arg(args, long);
473                     else
474                         value = va_arg(args, int);
475                     if (zxflag && value) {
476                         (void) dostr(&bp, ep, "0x", 0);
477                         if (len >= 2)
478                             len -= 2;
479                     }
480                     (void) fmtnum(&bp, ep, value,-16,0, ljust, len, zpad);
481                     break;
482                 case 's':
483                     strvalue = va_arg(args, char *);
484                     if (maxwidth > 0 || !pointflag) {
485                         if (pointflag && len > maxwidth)
486                             len = maxwidth; /* Adjust padding */
487                         (void) fmtstr(&bp, ep, strvalue, ljust, len, zpad,
488                                       maxwidth);
489                     }
490                     break;
491                 case 'c':
492                     ch = va_arg(args, int);
493                     dopr_outch(&bp, ep, ch);
494                     break;
495                 case '%':
496                     (void) dopr_outch(&bp, ep, ch);
497                     continue;
498                 default:
499                     ebuf[0] = ch;
500                     (void) strncpy(&ebuf[1], " is unsupported", ebufl);
501                     ebuf[(int)ebufl] = '\0';
502                     (void) dostr(&bp, ep, ebuf, 0);
503                 }
504                 break;
505             default:
506                 (void) dopr_outch(&bp, ep, ch);
507                 break;
508             }
509         }
510         *bp = '\0';
511 }
512
513
514 # if    !defined(HAS_NO_LONG_LONG)
515 /*
516  * fmtllnum() -- format long long number for output
517  */
518
519 static void
520 fmtllnum(bp, ep, value, base, dosign, ljust, len, zpad)
521         char **bp;                      /* current buffer pointer */
522         char *ep;                       /* end of buffer (-1) */
523         long long value;                /* number to format */
524         int base;                       /* number base */
525         int dosign;                     /* sign request */
526         int ljust;                      /* left justfication request */
527         int len;                        /* length request */
528         int zpad;                       /* zero padding request */
529 {
530         int signvalue = 0;
531         unsigned long long uvalue;
532         char convert[20];
533         int place = 0;
534         int padlen = 0; /* amount to pad */
535         int caps = 0;
536
537         uvalue = value;
538         if (dosign) {
539             if (value < 0) {
540                 signvalue = '-';
541                 uvalue = -value;
542             }
543         }
544         if (base < 0) {
545             caps = 1;
546             base = -base;
547         }
548         do {
549             convert[place++] = 
550                 (caps ? "0123456789ABCDEF" : "0123456789abcdef")
551                     [uvalue % (unsigned)base];
552             uvalue = (uvalue / (unsigned)base);
553         } while (uvalue && (place < (int)(sizeof(convert) - 1)));
554         convert[place] = 0;
555         padlen = len - place;
556         if (padlen < 0)
557             padlen = 0;
558         if(ljust)
559             padlen = -padlen;
560         if (zpad && padlen > 0) {
561             if (signvalue) {
562                 (void) dopr_outch(bp, ep, signvalue);
563                 --padlen;
564                 signvalue = 0;
565             }
566             while (padlen > 0) {
567                 (void) dopr_outch(bp, ep, zpad);
568                 --padlen;
569             }
570         }
571         while (padlen > 0) {
572             (void) dopr_outch(bp, ep, ' ');
573              --padlen;
574         }
575         if (signvalue)
576             (void) dopr_outch(bp, ep, signvalue);
577         while (place > 0)
578             (void) dopr_outch(bp, ep, convert[--place]);
579         while (padlen < 0) {
580             (void) dopr_outch(bp, ep, ' ');
581             ++padlen;
582         }
583 }
584 # endif /* !defined(HAS_NO_LONG_LONG) */
585
586
587 /*
588  * fmtnum() -- format number for output
589  */
590
591 static void
592 fmtnum(bp, ep, value, base, dosign, ljust, len, zpad)
593         char **bp;                      /* current buffer pointer */
594         char *ep;                       /* end of buffer (-1) */
595         long value;                     /* number to format */
596         int base;                       /* number base */
597         int dosign;                     /* sign request */
598         int ljust;                      /* left justfication request */
599         int len;                        /* length request */
600         int zpad;                       /* zero padding request */
601 {
602         int signvalue = 0;
603         unsigned long uvalue;
604         char convert[20];
605         int place = 0;
606         int padlen = 0; /* amount to pad */
607         int caps = 0;
608
609         uvalue = value;
610         if (dosign) {
611             if (value < 0) {
612                 signvalue = '-';
613                 uvalue = -value;
614             }
615         }
616         if (base < 0) {
617             caps = 1;
618             base = -base;
619         }
620         do {
621             convert[place++] = 
622                 (caps ? "0123456789ABCDEF" : "0123456789abcdef")
623                     [uvalue % (unsigned)base];
624             uvalue = (uvalue / (unsigned)base);
625         } while (uvalue && (place < (int)(sizeof(convert) - 1)));
626         convert[place] = 0;
627         padlen = len - place;
628         if (padlen < 0)
629             padlen = 0;
630         if(ljust)
631             padlen = -padlen;
632         if (zpad && padlen > 0) {
633             if (signvalue) {
634                 (void) dopr_outch(bp, ep, signvalue);
635                 --padlen;
636                 signvalue = 0;
637             }
638             while (padlen > 0) {
639                 (void) dopr_outch(bp, ep, zpad);
640                 --padlen;
641             }
642         }
643         while (padlen > 0) {
644             (void) dopr_outch(bp, ep, ' ');
645              --padlen;
646         }
647         if (signvalue)
648             (void) dopr_outch(bp, ep, signvalue);
649         while (place > 0)
650             (void) dopr_outch(bp, ep, convert[--place]);
651         while (padlen < 0) {
652             (void) dopr_outch(bp, ep, ' ');
653             ++padlen;
654         }
655 }
656
657
658 /*
659  * fmtstr() -- format string for output
660  */
661
662 static void
663 fmtstr(bp, ep, value, ljust, len, zpad, maxwidth)
664         char **bp;                      /* current buffer pointer */
665         char *ep;                       /* end of buffer (-1) */
666         char *value;                    /* string to format */
667         int ljust;                      /* left justification request */
668         int len;                        /* length request */
669         int zpad;                       /* zero padding request */
670         int maxwidth;                   /* maximum width request */
671 {
672         int padlen, strlen;     /* amount to pad */
673
674         if (value == 0)
675             value = "<NULL>";
676         for (strlen = 0; value[strlen]; ++ strlen)      /* strlen() */
677             ;
678         if ((strlen > maxwidth) && maxwidth)
679             strlen = maxwidth;
680         padlen = len - strlen;
681         if (padlen < 0)
682             padlen = 0;
683         if (ljust)
684             padlen = -padlen;
685         while (padlen > 0) {
686             (void) dopr_outch(bp, ep, ' ');
687             --padlen;
688         }
689         (void) dostr(bp, ep, value, maxwidth);
690         while (padlen < 0) {
691             (void) dopr_outch(bp, ep, ' ');
692             ++padlen;
693         }
694 }
695
696
697 /*
698  * dostr() -- do string output
699  */
700
701 static void
702 dostr(bp, ep, str, cut)
703         char **bp;                      /* current buffer pointer */
704         char *ep;                       /* end of buffer (-1) */
705         char *str;                      /* string to output */
706         int cut;                        /* limit on amount of string to output:
707                                          *   0 == no limit */
708 {
709         int f;
710
711         f = cut ? 1 : 0;
712         while (*str) {
713             if (f) {
714                 if (cut-- > 0)
715                     (void) dopr_outch(bp, ep, *str);
716             } else
717                 (void) dopr_outch(bp, ep, *str);
718             str++;
719         }
720 }
721
722
723 /*
724  * dopr_outch() -- output a character (or two)
725  */
726
727 static void
728 dopr_outch(bp, ep, c)
729         char **bp;                      /* current buffer pointer */
730         char *ep;                       /* end of buffer (-1) */
731         int c;                          /* character to output */
732 {
733         register char *cp = *bp;
734
735         if (iscntrl(c) && c != '\n' && c != '\t') {
736             c = '@' + (c & 0x1F);
737             if (cp < ep)
738                 *cp++ = '^';
739             Length++;
740         }
741         if (cp < ep)
742             *cp++ = c;
743         *bp = cp;
744         Length++;
745 }
746
747 #else   /* !defined(USE_LIB_SNPF) */
748 char snpf_d1[] = "d"; char *snpf_d2 = snpf_d1;
749 #endif  /* defined(USE_LIB_SNPF) */