leafnode  1.12.0
About: Leafnode is a store & forward NNTP proxy for small (dialup) sites.
  Fossies Dox: leafnode-1.12.0.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

snprintf.c
Go to the documentation of this file.
1/*
2 * poor man's snprintf() - for systems which don't have their own
3 *
4 * This version of snprintf() currently supports only %s, %c, %d, %u,
5 * %ld, %lu, %li, %i. It supports the 0, + and width modifiers only for decimal
6 * output (%[l]{d|u|i}).
7 *
8 * Copyright (c) Cornelius Krasel 2000.
9 * Modified by Matthias Andree <matthias.andree@gmx.de>.
10 * Modifications (C)opyright 2002 - 2004.
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to
14 * deal in the Software without restriction, including without limitation the
15 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 * sell copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 * IN THE SOFTWARE.
29 */
30
31#include "leafnode.h"
32
33#ifndef HAVE_WORKING_SNPRINTF
34
35#include <stdarg.h>
36#include <stdlib.h>
37#include <string.h>
38#include <stdio.h>
39
40/** format unsigned value u into p */
41static void fmtu(char *p, unsigned long u) {
42 unsigned int len = 0;
43 unsigned long i = u, ni;
44 unsigned char b[22];
45 do {
46 ni = i / 10;
47 b[len++] = i - 10*ni;
48 i = ni;
49 } while (i);
50
51 while (len) {
52 *p++ = "0123456789"[b[--len]];
53 }
54 *p = '\0';
55}
56
57/** format signed value s into p, prefix asign if its nonzero and the
58 * value is positive. asign is usually '+' or ' '. */
59static inline void fmts(char *p, long s, char asign) {
60 if (s < 0) {
61 *p++ = '-';
62 fmtu(p, -s);
63 } else {
64 if (asign)
65 *p++ = asign;
66 fmtu(p, s);
67 }
68}
69
70int
71ln_vsnprintf(char *str, size_t n, const char *format, va_list ap)
72{
73 const char *p;
74 char *q;
75 int flag = 0;
76 size_t width = 0;
77 char fill = ' ';
78 int lflag = 0; /* checking for longs */
79 int asign = 0; /* always show sign */
80 size_t i = 1; /* because the terminating \0 also counts */
81 size_t len, olen;
82 char buf[30]; /* buffer for converting longs and ints */
83
84 char *s;
85 char c;
86
87 p = format;
88 q = str;
89 while (p && *p) {
90 if ((*p == '%') && !flag) {
91 /* swallow the %, switch to % mode and initialize */
92 lflag = 0;
93 flag = 1;
94 asign = 0; /* can be 0, '+' or later ' ' (' ' is unimplemented) */
95 fill = ' ';
96 width = 0;
97 p++;
98 } else if (flag) {
99 /* % mode */
100 switch (*p) {
101 case 's': case 'm': {
102 if (*p == 's')
103 s = va_arg(ap, char *);
104 else
105 s = strerror(errno);
106 olen = len = strlen(s);
107 if (len > (n - i))
108 len = n - i;
109 *q = '\0';
110 strncat(q, s, len);
111 p++;
112 q += len;
113 i += olen;
114 flag = 0;
115 break;
116 }
117 case 'u':{
118 unsigned long u;
119 if (lflag) {
120 u = va_arg(ap, unsigned long);
121 } else {
122 u = (unsigned long)va_arg(ap, unsigned int);
123 }
124 fmtu(buf, u);
125 goto printdec;
126 }
127 case 'd': case 'i': {
128 long l;
129 if (lflag) {
130 l = va_arg(ap, long);
131 } else {
132 l = (long)va_arg(ap, int);
133 }
134 fmts(buf, l, asign);
135printdec:
136 olen = len = strlen(buf);
137 if (width) {
138 int off = !!asign;
139 if (len < width) {
140 switch (fill) {
141 case ' ':
142 memmove(buf + width - len, buf, len + 1);
143 memset(buf, fill, width - len);
144 break;
145 case '0':
146 memmove(buf + off + width - len, buf + off, len + 1 - off);
147 memset(buf + off, fill, width - len);
148 break;
149 default:
150 abort();
151 }
152 }
153 olen = len = strlen(buf);
154 }
155 if (len > (n - i))
156 len = n - i;
157 *q = '\0';
158 strncat(q, buf, len);
159 q += len;
160 i += olen;
161 flag = 0;
162 p++;
163 break;
164 }
165 case 'l':{
166 /* next argument will be long */
167 lflag = 1;
168 p++;
169 break;
170 }
171 case 'c':{
172 c = va_arg(ap, int);
173 flag = 0;
174 if (i < n)
175 *q++ = c;
176 i++;
177 p++;
178 break;
179 }
180 case '%':{
181 flag = 0;
182 if (i < n)
183 *q++ = *p++;
184 i++;
185 break;
186 }
187 case '0':
188 if (fill == ' ' && width == 0)
189 fill='0';
190 else
191 width *= 10;
192 p++;
193 break;
194 case '1': case '2': case '3': case '4': case '5':
195 case '6': case '7': case '8': case '9':
196 width = width * 10 + *p - '0';
197 p++;
198 break;
199 case '+':
200 asign = '+';
201 p++;
202 break;
203 default:
204 abort();
205 break;
206 }
207 } else {
208 if (i < n) {
209 *q++ = *p;
210 }
211 p++;
212 i++;
213 }
214 }
215 va_end(ap);
216 *q = '\0';
217 return (i - 1);
218}
219
220int
221ln_snprintf(char *str, size_t n, const char *format, ...)
222{
223 int r;
224 va_list ap;
225
226 va_start(ap, format);
227 r = ln_vsnprintf(str, n, format, ap);
228 va_end(ap);
229 return r;
230}
231
232#endif
#define len
Definition: mastring.c:31
int ln_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition: snprintf.c:71
static void fmtu(char *p, unsigned long u)
Definition: snprintf.c:41
int ln_snprintf(char *str, size_t n, const char *format,...)
Definition: snprintf.c:221
static void fmts(char *p, long s, char asign)
Definition: snprintf.c:59