tarruby 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. data/README.txt +99 -0
  2. data/ext/extconf.rb +19 -0
  3. data/ext/libtar/COPYRIGHT +35 -0
  4. data/ext/libtar/ChangeLog +243 -0
  5. data/ext/libtar/ChangeLog-1.0.x +141 -0
  6. data/ext/libtar/INSTALL +183 -0
  7. data/ext/libtar/Makefile.in +51 -0
  8. data/ext/libtar/README +121 -0
  9. data/ext/libtar/TODO +10 -0
  10. data/ext/libtar/autoconf/ac_path_generic.m4 +136 -0
  11. data/ext/libtar/autoconf/aclocal.m4 +199 -0
  12. data/ext/libtar/autoconf/encap.m4 +133 -0
  13. data/ext/libtar/autoconf/install-sh +251 -0
  14. data/ext/libtar/autom4te.cache/output.0 +8102 -0
  15. data/ext/libtar/autom4te.cache/requests +112 -0
  16. data/ext/libtar/autom4te.cache/traces.0 +382 -0
  17. data/ext/libtar/compat/ChangeLog +31 -0
  18. data/ext/libtar/compat/README +12 -0
  19. data/ext/libtar/compat/TODO +4 -0
  20. data/ext/libtar/compat/basename.c +91 -0
  21. data/ext/libtar/compat/compat.h +260 -0
  22. data/ext/libtar/compat/dirname.c +96 -0
  23. data/ext/libtar/compat/fnmatch.c +237 -0
  24. data/ext/libtar/compat/gethostbyname_r.c +41 -0
  25. data/ext/libtar/compat/gethostname.c +36 -0
  26. data/ext/libtar/compat/getservbyname_r.c +41 -0
  27. data/ext/libtar/compat/glob.c +898 -0
  28. data/ext/libtar/compat/inet_aton.c +27 -0
  29. data/ext/libtar/compat/module.ac +591 -0
  30. data/ext/libtar/compat/snprintf.c +788 -0
  31. data/ext/libtar/compat/strdup.c +62 -0
  32. data/ext/libtar/compat/strlcat.c +72 -0
  33. data/ext/libtar/compat/strlcpy.c +68 -0
  34. data/ext/libtar/compat/strmode.c +199 -0
  35. data/ext/libtar/compat/strrstr.c +40 -0
  36. data/ext/libtar/compat/strsep.c +87 -0
  37. data/ext/libtar/config.h.in +187 -0
  38. data/ext/libtar/configure +8102 -0
  39. data/ext/libtar/configure.ac +114 -0
  40. data/ext/libtar/doc/Makefile.in +152 -0
  41. data/ext/libtar/doc/tar_append_file.3 +50 -0
  42. data/ext/libtar/doc/tar_block_read.3 +24 -0
  43. data/ext/libtar/doc/tar_extract_all.3 +43 -0
  44. data/ext/libtar/doc/tar_extract_file.3 +84 -0
  45. data/ext/libtar/doc/tar_open.3 +97 -0
  46. data/ext/libtar/doc/th_get_pathname.3 +63 -0
  47. data/ext/libtar/doc/th_print_long_ls.3 +22 -0
  48. data/ext/libtar/doc/th_read.3 +34 -0
  49. data/ext/libtar/doc/th_set_from_stat.3 +45 -0
  50. data/ext/libtar/lib/Makefile.in +92 -0
  51. data/ext/libtar/lib/append.c +272 -0
  52. data/ext/libtar/lib/block.c +384 -0
  53. data/ext/libtar/lib/decode.c +130 -0
  54. data/ext/libtar/lib/encode.c +237 -0
  55. data/ext/libtar/lib/extract.c +656 -0
  56. data/ext/libtar/lib/handle.c +150 -0
  57. data/ext/libtar/lib/internal.h +46 -0
  58. data/ext/libtar/lib/libtar.h +311 -0
  59. data/ext/libtar/lib/output.c +146 -0
  60. data/ext/libtar/lib/util.c +153 -0
  61. data/ext/libtar/lib/wrapper.c +175 -0
  62. data/ext/libtar/libtar/Makefile.in +73 -0
  63. data/ext/libtar/libtar/libtar.c +363 -0
  64. data/ext/libtar/listhash/ChangeLog +15 -0
  65. data/ext/libtar/listhash/TODO +21 -0
  66. data/ext/libtar/listhash/hash.c.in +344 -0
  67. data/ext/libtar/listhash/hash_new.3.in +74 -0
  68. data/ext/libtar/listhash/list.c.in +458 -0
  69. data/ext/libtar/listhash/list_new.3.in +86 -0
  70. data/ext/libtar/listhash/listhash.h.in +196 -0
  71. data/ext/libtar/listhash/module.ac +21 -0
  72. data/ext/libtar/win32/config.h +190 -0
  73. data/ext/libtar/win32/dirent.c +115 -0
  74. data/ext/libtar/win32/dirent.h +24 -0
  75. data/ext/libtar/win32/grp.h +4 -0
  76. data/ext/libtar/win32/listhash/libtar_hash.c +344 -0
  77. data/ext/libtar/win32/listhash/libtar_list.c +458 -0
  78. data/ext/libtar/win32/listhash/libtar_listhash.h +196 -0
  79. data/ext/libtar/win32/pwd.h +4 -0
  80. data/ext/libtar/win32/sys/param.h +8 -0
  81. data/ext/libtar/win32/tar.h +35 -0
  82. data/ext/libtar/win32/utime.h +6 -0
  83. data/ext/libtar/win32/win32/types.h +10 -0
  84. data/ext/tarruby.c +648 -0
  85. metadata +150 -0
@@ -0,0 +1,788 @@
1
+ /**************************************************************
2
+ * Original:
3
+ * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
4
+ * A bombproof version of doprnt (dopr) included.
5
+ * Sigh. This sort of thing is always nasty do deal with. Note that
6
+ * the version here does not include floating point...
7
+ *
8
+ * snprintf() is used instead of sprintf() as it does limit checks
9
+ * for string length. This covers a nasty loophole.
10
+ *
11
+ * The other functions are there to prevent NULL pointers from
12
+ * causing nast effects.
13
+ *
14
+ * More Recently:
15
+ * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
16
+ * This was ugly. It is still ugly. I opted out of floating point
17
+ * numbers, but the formatter understands just about everything
18
+ * from the normal C string format, at least as far as I can tell from
19
+ * the Solaris 2.5 printf(3S) man page.
20
+ *
21
+ * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
22
+ * Ok, added some minimal floating point support, which means this
23
+ * probably requires libm on most operating systems. Don't yet
24
+ * support the exponent (e,E) and sigfig (g,G). Also, fmtint()
25
+ * was pretty badly broken, it just wasn't being exercised in ways
26
+ * which showed it, so that's been fixed. Also, formated the code
27
+ * to mutt conventions, and removed dead code left over from the
28
+ * original. Also, there is now a builtin-test, just compile with:
29
+ * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
30
+ * and run snprintf for results.
31
+ *
32
+ * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
33
+ * The PGP code was using unsigned hexadecimal formats.
34
+ * Unfortunately, unsigned formats simply didn't work.
35
+ *
36
+ * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
37
+ * The original code assumed that both snprintf() and vsnprintf() were
38
+ * missing. Some systems only have snprintf() but not vsnprintf(), so
39
+ * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
40
+ *
41
+ **************************************************************/
42
+
43
+ #include <config.h>
44
+
45
+ #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
46
+
47
+ #include <string.h>
48
+ # include <ctype.h>
49
+ #include <sys/types.h>
50
+
51
+ /* Define this as a fall through, HAVE_STDARG_H is probably already set */
52
+
53
+ #define HAVE_VARARGS_H
54
+
55
+ /* varargs declarations: */
56
+
57
+ #if defined(HAVE_STDARG_H)
58
+ # include <stdarg.h>
59
+ # define HAVE_STDARGS /* let's hope that works everywhere (mj) */
60
+ # define VA_LOCAL_DECL va_list ap
61
+ # define VA_START(f) va_start(ap, f)
62
+ # define VA_SHIFT(v,t) ; /* no-op for ANSI */
63
+ # define VA_END va_end(ap)
64
+ #else
65
+ # if defined(HAVE_VARARGS_H)
66
+ # include <varargs.h>
67
+ # undef HAVE_STDARGS
68
+ # define VA_LOCAL_DECL va_list ap
69
+ # define VA_START(f) va_start(ap) /* f is ignored! */
70
+ # define VA_SHIFT(v,t) v = va_arg(ap,t)
71
+ # define VA_END va_end(ap)
72
+ # else
73
+ /*XX ** NO VARARGS ** XX*/
74
+ # endif
75
+ #endif
76
+
77
+ /*int snprintf (char *str, size_t count, const char *fmt, ...);*/
78
+ /*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/
79
+
80
+ static void dopr (char *buffer, size_t maxlen, const char *format,
81
+ va_list args);
82
+ static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
83
+ char *value, int flags, int min, int max);
84
+ static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
85
+ long value, int base, int min, int max, int flags);
86
+ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
87
+ long double fvalue, int min, int max, int flags);
88
+ static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
89
+
90
+ /*
91
+ * dopr(): poor man's version of doprintf
92
+ */
93
+
94
+ /* format read states */
95
+ #define DP_S_DEFAULT 0
96
+ #define DP_S_FLAGS 1
97
+ #define DP_S_MIN 2
98
+ #define DP_S_DOT 3
99
+ #define DP_S_MAX 4
100
+ #define DP_S_MOD 5
101
+ #define DP_S_CONV 6
102
+ #define DP_S_DONE 7
103
+
104
+ /* format flags - Bits */
105
+ #define DP_F_MINUS (1 << 0)
106
+ #define DP_F_PLUS (1 << 1)
107
+ #define DP_F_SPACE (1 << 2)
108
+ #define DP_F_NUM (1 << 3)
109
+ #define DP_F_ZERO (1 << 4)
110
+ #define DP_F_UP (1 << 5)
111
+ #define DP_F_UNSIGNED (1 << 6)
112
+
113
+ /* Conversion Flags */
114
+ #define DP_C_SHORT 1
115
+ #define DP_C_LONG 2
116
+ #define DP_C_LDOUBLE 3
117
+
118
+ #define char_to_int(p) (p - '0')
119
+ #define MAX(p,q) ((p >= q) ? p : q)
120
+
121
+ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
122
+ {
123
+ char ch;
124
+ long value;
125
+ long double fvalue;
126
+ char *strvalue;
127
+ int min;
128
+ int max;
129
+ int state;
130
+ int flags;
131
+ int cflags;
132
+ size_t currlen;
133
+
134
+ state = DP_S_DEFAULT;
135
+ currlen = flags = cflags = min = 0;
136
+ max = -1;
137
+ ch = *format++;
138
+
139
+ while (state != DP_S_DONE)
140
+ {
141
+ if ((ch == '\0') || (currlen >= maxlen))
142
+ state = DP_S_DONE;
143
+
144
+ switch(state)
145
+ {
146
+ case DP_S_DEFAULT:
147
+ if (ch == '%')
148
+ state = DP_S_FLAGS;
149
+ else
150
+ dopr_outch (buffer, &currlen, maxlen, ch);
151
+ ch = *format++;
152
+ break;
153
+ case DP_S_FLAGS:
154
+ switch (ch)
155
+ {
156
+ case '-':
157
+ flags |= DP_F_MINUS;
158
+ ch = *format++;
159
+ break;
160
+ case '+':
161
+ flags |= DP_F_PLUS;
162
+ ch = *format++;
163
+ break;
164
+ case ' ':
165
+ flags |= DP_F_SPACE;
166
+ ch = *format++;
167
+ break;
168
+ case '#':
169
+ flags |= DP_F_NUM;
170
+ ch = *format++;
171
+ break;
172
+ case '0':
173
+ flags |= DP_F_ZERO;
174
+ ch = *format++;
175
+ break;
176
+ default:
177
+ state = DP_S_MIN;
178
+ break;
179
+ }
180
+ break;
181
+ case DP_S_MIN:
182
+ if (isdigit((unsigned char)ch))
183
+ {
184
+ min = 10*min + char_to_int (ch);
185
+ ch = *format++;
186
+ }
187
+ else if (ch == '*')
188
+ {
189
+ min = va_arg (args, int);
190
+ ch = *format++;
191
+ state = DP_S_DOT;
192
+ }
193
+ else
194
+ state = DP_S_DOT;
195
+ break;
196
+ case DP_S_DOT:
197
+ if (ch == '.')
198
+ {
199
+ state = DP_S_MAX;
200
+ ch = *format++;
201
+ }
202
+ else
203
+ state = DP_S_MOD;
204
+ break;
205
+ case DP_S_MAX:
206
+ if (isdigit((unsigned char)ch))
207
+ {
208
+ if (max < 0)
209
+ max = 0;
210
+ max = 10*max + char_to_int (ch);
211
+ ch = *format++;
212
+ }
213
+ else if (ch == '*')
214
+ {
215
+ max = va_arg (args, int);
216
+ ch = *format++;
217
+ state = DP_S_MOD;
218
+ }
219
+ else
220
+ state = DP_S_MOD;
221
+ break;
222
+ case DP_S_MOD:
223
+ /* Currently, we don't support Long Long, bummer */
224
+ switch (ch)
225
+ {
226
+ case 'h':
227
+ cflags = DP_C_SHORT;
228
+ ch = *format++;
229
+ break;
230
+ case 'l':
231
+ cflags = DP_C_LONG;
232
+ ch = *format++;
233
+ break;
234
+ case 'L':
235
+ cflags = DP_C_LDOUBLE;
236
+ ch = *format++;
237
+ break;
238
+ default:
239
+ break;
240
+ }
241
+ state = DP_S_CONV;
242
+ break;
243
+ case DP_S_CONV:
244
+ switch (ch)
245
+ {
246
+ case 'd':
247
+ case 'i':
248
+ if (cflags == DP_C_SHORT)
249
+ value = va_arg (args, short int);
250
+ else if (cflags == DP_C_LONG)
251
+ value = va_arg (args, long int);
252
+ else
253
+ value = va_arg (args, int);
254
+ fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
255
+ break;
256
+ case 'o':
257
+ flags |= DP_F_UNSIGNED;
258
+ if (cflags == DP_C_SHORT)
259
+ value = va_arg (args, unsigned short int);
260
+ else if (cflags == DP_C_LONG)
261
+ value = va_arg (args, unsigned long int);
262
+ else
263
+ value = va_arg (args, unsigned int);
264
+ fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
265
+ break;
266
+ case 'u':
267
+ flags |= DP_F_UNSIGNED;
268
+ if (cflags == DP_C_SHORT)
269
+ value = va_arg (args, unsigned short int);
270
+ else if (cflags == DP_C_LONG)
271
+ value = va_arg (args, unsigned long int);
272
+ else
273
+ value = va_arg (args, unsigned int);
274
+ fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
275
+ break;
276
+ case 'X':
277
+ flags |= DP_F_UP;
278
+ case 'x':
279
+ flags |= DP_F_UNSIGNED;
280
+ if (cflags == DP_C_SHORT)
281
+ value = va_arg (args, unsigned short int);
282
+ else if (cflags == DP_C_LONG)
283
+ value = va_arg (args, unsigned long int);
284
+ else
285
+ value = va_arg (args, unsigned int);
286
+ fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
287
+ break;
288
+ case 'f':
289
+ if (cflags == DP_C_LDOUBLE)
290
+ fvalue = va_arg (args, long double);
291
+ else
292
+ fvalue = va_arg (args, double);
293
+ /* um, floating point? */
294
+ fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
295
+ break;
296
+ case 'E':
297
+ flags |= DP_F_UP;
298
+ case 'e':
299
+ if (cflags == DP_C_LDOUBLE)
300
+ fvalue = va_arg (args, long double);
301
+ else
302
+ fvalue = va_arg (args, double);
303
+ break;
304
+ case 'G':
305
+ flags |= DP_F_UP;
306
+ case 'g':
307
+ if (cflags == DP_C_LDOUBLE)
308
+ fvalue = va_arg (args, long double);
309
+ else
310
+ fvalue = va_arg (args, double);
311
+ break;
312
+ case 'c':
313
+ dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
314
+ break;
315
+ case 's':
316
+ strvalue = va_arg (args, char *);
317
+ if (max < 0)
318
+ max = maxlen; /* ie, no max */
319
+ fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
320
+ break;
321
+ case 'p':
322
+ strvalue = va_arg (args, void *);
323
+ fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
324
+ break;
325
+ case 'n':
326
+ if (cflags == DP_C_SHORT)
327
+ {
328
+ short int *num;
329
+ num = va_arg (args, short int *);
330
+ *num = currlen;
331
+ }
332
+ else if (cflags == DP_C_LONG)
333
+ {
334
+ long int *num;
335
+ num = va_arg (args, long int *);
336
+ *num = currlen;
337
+ }
338
+ else
339
+ {
340
+ int *num;
341
+ num = va_arg (args, int *);
342
+ *num = currlen;
343
+ }
344
+ break;
345
+ case '%':
346
+ dopr_outch (buffer, &currlen, maxlen, ch);
347
+ break;
348
+ case 'w':
349
+ /* not supported yet, treat as next char */
350
+ ch = *format++;
351
+ break;
352
+ default:
353
+ /* Unknown, skip */
354
+ break;
355
+ }
356
+ ch = *format++;
357
+ state = DP_S_DEFAULT;
358
+ flags = cflags = min = 0;
359
+ max = -1;
360
+ break;
361
+ case DP_S_DONE:
362
+ break;
363
+ default:
364
+ /* hmm? */
365
+ break; /* some picky compilers need this */
366
+ }
367
+ }
368
+ if (currlen < maxlen - 1)
369
+ buffer[currlen] = '\0';
370
+ else
371
+ buffer[maxlen - 1] = '\0';
372
+ }
373
+
374
+ static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
375
+ char *value, int flags, int min, int max)
376
+ {
377
+ int padlen, strln; /* amount to pad */
378
+ int cnt = 0;
379
+
380
+ if (value == 0)
381
+ {
382
+ value = "<NULL>";
383
+ }
384
+
385
+ for (strln = 0; value[strln]; ++strln); /* strlen */
386
+ padlen = min - strln;
387
+ if (padlen < 0)
388
+ padlen = 0;
389
+ if (flags & DP_F_MINUS)
390
+ padlen = -padlen; /* Left Justify */
391
+
392
+ while ((padlen > 0) && (cnt < max))
393
+ {
394
+ dopr_outch (buffer, currlen, maxlen, ' ');
395
+ --padlen;
396
+ ++cnt;
397
+ }
398
+ while (*value && (cnt < max))
399
+ {
400
+ dopr_outch (buffer, currlen, maxlen, *value++);
401
+ ++cnt;
402
+ }
403
+ while ((padlen < 0) && (cnt < max))
404
+ {
405
+ dopr_outch (buffer, currlen, maxlen, ' ');
406
+ ++padlen;
407
+ ++cnt;
408
+ }
409
+ }
410
+
411
+ /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
412
+
413
+ static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
414
+ long value, int base, int min, int max, int flags)
415
+ {
416
+ int signvalue = 0;
417
+ unsigned long uvalue;
418
+ char convert[20];
419
+ int place = 0;
420
+ int spadlen = 0; /* amount to space pad */
421
+ int zpadlen = 0; /* amount to zero pad */
422
+ int caps = 0;
423
+
424
+ if (max < 0)
425
+ max = 0;
426
+
427
+ uvalue = value;
428
+
429
+ if(!(flags & DP_F_UNSIGNED))
430
+ {
431
+ if( value < 0 ) {
432
+ signvalue = '-';
433
+ uvalue = -value;
434
+ }
435
+ else
436
+ if (flags & DP_F_PLUS) /* Do a sign (+/i) */
437
+ signvalue = '+';
438
+ else
439
+ if (flags & DP_F_SPACE)
440
+ signvalue = ' ';
441
+ }
442
+
443
+ if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
444
+
445
+ do {
446
+ convert[place++] =
447
+ (caps? "0123456789ABCDEF":"0123456789abcdef")
448
+ [uvalue % (unsigned)base ];
449
+ uvalue = (uvalue / (unsigned)base );
450
+ } while(uvalue && (place < 20));
451
+ if (place == 20) place--;
452
+ convert[place] = 0;
453
+
454
+ zpadlen = max - place;
455
+ spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
456
+ if (zpadlen < 0) zpadlen = 0;
457
+ if (spadlen < 0) spadlen = 0;
458
+ if (flags & DP_F_ZERO)
459
+ {
460
+ zpadlen = MAX(zpadlen, spadlen);
461
+ spadlen = 0;
462
+ }
463
+ if (flags & DP_F_MINUS)
464
+ spadlen = -spadlen; /* Left Justifty */
465
+
466
+ #ifdef DEBUG_SNPRINTF
467
+ dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
468
+ zpadlen, spadlen, min, max, place));
469
+ #endif
470
+
471
+ /* Spaces */
472
+ while (spadlen > 0)
473
+ {
474
+ dopr_outch (buffer, currlen, maxlen, ' ');
475
+ --spadlen;
476
+ }
477
+
478
+ /* Sign */
479
+ if (signvalue)
480
+ dopr_outch (buffer, currlen, maxlen, signvalue);
481
+
482
+ /* Zeros */
483
+ if (zpadlen > 0)
484
+ {
485
+ while (zpadlen > 0)
486
+ {
487
+ dopr_outch (buffer, currlen, maxlen, '0');
488
+ --zpadlen;
489
+ }
490
+ }
491
+
492
+ /* Digits */
493
+ while (place > 0)
494
+ dopr_outch (buffer, currlen, maxlen, convert[--place]);
495
+
496
+ /* Left Justified spaces */
497
+ while (spadlen < 0) {
498
+ dopr_outch (buffer, currlen, maxlen, ' ');
499
+ ++spadlen;
500
+ }
501
+ }
502
+
503
+ static long double abs_val (long double value)
504
+ {
505
+ long double result = value;
506
+
507
+ if (value < 0)
508
+ result = -value;
509
+
510
+ return result;
511
+ }
512
+
513
+ static long double pow10 (int exp)
514
+ {
515
+ long double result = 1;
516
+
517
+ while (exp)
518
+ {
519
+ result *= 10;
520
+ exp--;
521
+ }
522
+
523
+ return result;
524
+ }
525
+
526
+ static long round (long double value)
527
+ {
528
+ long intpart;
529
+
530
+ intpart = value;
531
+ value = value - intpart;
532
+ if (value >= 0.5)
533
+ intpart++;
534
+
535
+ return intpart;
536
+ }
537
+
538
+ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
539
+ long double fvalue, int min, int max, int flags)
540
+ {
541
+ int signvalue = 0;
542
+ long double ufvalue;
543
+ char iconvert[20];
544
+ char fconvert[20];
545
+ int iplace = 0;
546
+ int fplace = 0;
547
+ int padlen = 0; /* amount to pad */
548
+ int zpadlen = 0;
549
+ int caps = 0;
550
+ long intpart;
551
+ long fracpart;
552
+
553
+ /*
554
+ * AIX manpage says the default is 0, but Solaris says the default
555
+ * is 6, and sprintf on AIX defaults to 6
556
+ */
557
+ if (max < 0)
558
+ max = 6;
559
+
560
+ ufvalue = abs_val (fvalue);
561
+
562
+ if (fvalue < 0)
563
+ signvalue = '-';
564
+ else
565
+ if (flags & DP_F_PLUS) /* Do a sign (+/i) */
566
+ signvalue = '+';
567
+ else
568
+ if (flags & DP_F_SPACE)
569
+ signvalue = ' ';
570
+
571
+ #if 0
572
+ if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
573
+ #endif
574
+
575
+ intpart = ufvalue;
576
+
577
+ /*
578
+ * Sorry, we only support 9 digits past the decimal because of our
579
+ * conversion method
580
+ */
581
+ if (max > 9)
582
+ max = 9;
583
+
584
+ /* We "cheat" by converting the fractional part to integer by
585
+ * multiplying by a factor of 10
586
+ */
587
+ fracpart = round ((pow10 (max)) * (ufvalue - intpart));
588
+
589
+ if (fracpart >= pow10 (max))
590
+ {
591
+ intpart++;
592
+ fracpart -= pow10 (max);
593
+ }
594
+
595
+ #ifdef DEBUG_SNPRINTF
596
+ dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart));
597
+ #endif
598
+
599
+ /* Convert integer part */
600
+ do {
601
+ iconvert[iplace++] =
602
+ (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];
603
+ intpart = (intpart / 10);
604
+ } while(intpart && (iplace < 20));
605
+ if (iplace == 20) iplace--;
606
+ iconvert[iplace] = 0;
607
+
608
+ /* Convert fractional part */
609
+ do {
610
+ fconvert[fplace++] =
611
+ (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
612
+ fracpart = (fracpart / 10);
613
+ } while(fracpart && (fplace < 20));
614
+ if (fplace == 20) fplace--;
615
+ fconvert[fplace] = 0;
616
+
617
+ /* -1 for decimal point, another -1 if we are printing a sign */
618
+ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
619
+ zpadlen = max - fplace;
620
+ if (zpadlen < 0)
621
+ zpadlen = 0;
622
+ if (padlen < 0)
623
+ padlen = 0;
624
+ if (flags & DP_F_MINUS)
625
+ padlen = -padlen; /* Left Justifty */
626
+
627
+ if ((flags & DP_F_ZERO) && (padlen > 0))
628
+ {
629
+ if (signvalue)
630
+ {
631
+ dopr_outch (buffer, currlen, maxlen, signvalue);
632
+ --padlen;
633
+ signvalue = 0;
634
+ }
635
+ while (padlen > 0)
636
+ {
637
+ dopr_outch (buffer, currlen, maxlen, '0');
638
+ --padlen;
639
+ }
640
+ }
641
+ while (padlen > 0)
642
+ {
643
+ dopr_outch (buffer, currlen, maxlen, ' ');
644
+ --padlen;
645
+ }
646
+ if (signvalue)
647
+ dopr_outch (buffer, currlen, maxlen, signvalue);
648
+
649
+ while (iplace > 0)
650
+ dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
651
+
652
+ /*
653
+ * Decimal point. This should probably use locale to find the correct
654
+ * char to print out.
655
+ */
656
+ dopr_outch (buffer, currlen, maxlen, '.');
657
+
658
+ while (fplace > 0)
659
+ dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
660
+
661
+ while (zpadlen > 0)
662
+ {
663
+ dopr_outch (buffer, currlen, maxlen, '0');
664
+ --zpadlen;
665
+ }
666
+
667
+ while (padlen < 0)
668
+ {
669
+ dopr_outch (buffer, currlen, maxlen, ' ');
670
+ ++padlen;
671
+ }
672
+ }
673
+
674
+ static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
675
+ {
676
+ if (*currlen < maxlen)
677
+ buffer[(*currlen)++] = c;
678
+ }
679
+ #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
680
+
681
+ #ifndef HAVE_VSNPRINTF
682
+ int mutt_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
683
+ {
684
+ str[0] = 0;
685
+ dopr(str, count, fmt, args);
686
+ return(strlen(str));
687
+ }
688
+ #endif /* !HAVE_VSNPRINTF */
689
+
690
+ #ifndef HAVE_SNPRINTF
691
+ /* VARARGS3 */
692
+ #ifdef HAVE_STDARGS
693
+ int mutt_snprintf (char *str,size_t count,const char *fmt,...)
694
+ #else
695
+ int mutt_snprintf (va_alist) va_dcl
696
+ #endif
697
+ {
698
+ #ifndef HAVE_STDARGS
699
+ char *str;
700
+ size_t count;
701
+ char *fmt;
702
+ #endif
703
+ VA_LOCAL_DECL;
704
+
705
+ VA_START (fmt);
706
+ VA_SHIFT (str, char *);
707
+ VA_SHIFT (count, size_t );
708
+ VA_SHIFT (fmt, char *);
709
+ (void) mutt_vsnprintf(str, count, fmt, ap);
710
+ VA_END;
711
+ return(strlen(str));
712
+ }
713
+
714
+ #ifdef TEST_SNPRINTF
715
+ #ifndef LONG_STRING
716
+ #define LONG_STRING 1024
717
+ #endif
718
+ int main (void)
719
+ {
720
+ char buf1[LONG_STRING];
721
+ char buf2[LONG_STRING];
722
+ char *fp_fmt[] = {
723
+ "%-1.5f",
724
+ "%1.5f",
725
+ "%123.9f",
726
+ "%10.5f",
727
+ "% 10.5f",
728
+ "%+22.9f",
729
+ "%+4.9f",
730
+ "%01.3f",
731
+ "%4f",
732
+ "%3.1f",
733
+ "%3.2f",
734
+ NULL
735
+ };
736
+ double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
737
+ 0.9996, 1.996, 4.136, 0};
738
+ char *int_fmt[] = {
739
+ "%-1.5d",
740
+ "%1.5d",
741
+ "%123.9d",
742
+ "%5.5d",
743
+ "%10.5d",
744
+ "% 10.5d",
745
+ "%+22.33d",
746
+ "%01.3d",
747
+ "%4d",
748
+ NULL
749
+ };
750
+ long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
751
+ int x, y;
752
+ int fail = 0;
753
+ int num = 0;
754
+
755
+ printf ("Testing snprintf format codes against system sprintf...\n");
756
+
757
+ for (x = 0; fp_fmt[x] != NULL ; x++)
758
+ for (y = 0; fp_nums[y] != 0 ; y++)
759
+ {
760
+ mutt_snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]);
761
+ sprintf (buf2, fp_fmt[x], fp_nums[y]);
762
+ if (strcmp (buf1, buf2))
763
+ {
764
+ printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
765
+ fp_fmt[x], buf1, buf2);
766
+ fail++;
767
+ }
768
+ num++;
769
+ }
770
+
771
+ for (x = 0; int_fmt[x] != NULL ; x++)
772
+ for (y = 0; int_nums[y] != 0 ; y++)
773
+ {
774
+ mutt_snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]);
775
+ sprintf (buf2, int_fmt[x], int_nums[y]);
776
+ if (strcmp (buf1, buf2))
777
+ {
778
+ printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
779
+ int_fmt[x], buf1, buf2);
780
+ fail++;
781
+ }
782
+ num++;
783
+ }
784
+ printf ("%d tests failed out of %d.\n", fail, num);
785
+ }
786
+ #endif /* SNPRINTF_TEST */
787
+
788
+ #endif /* !HAVE_SNPRINTF */