vfprintf.c (6589B)
1 /* -*-comment-start: "//";comment-end:""-*- 2 * GNU Mes --- Maxwell Equations of Software 3 * Copyright © 2017,2018,2019 Jan (janneke) Nieuwenhuizen <janneke@gnu.org> 4 * 5 * This file is part of GNU Mes. 6 * 7 * GNU Mes is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 3 of the License, or (at 10 * your option) any later version. 11 * 12 * GNU Mes is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include <mes/lib.h> 22 #include <stdarg.h> 23 #include <stdio.h> 24 #include <string.h> 25 26 int 27 vfprintf (FILE * f, char const *format, va_list ap) 28 { 29 int fd = (long) f; 30 char const *p = format; 31 int count = 0; 32 while (*p) 33 if (*p != '%') 34 { 35 count++; 36 fputc (*p++, f); 37 } 38 else 39 { 40 p++; 41 char c = *p; 42 int left_p = 0; 43 int precision = -1; 44 int width = -1; 45 if (c == '-') 46 { 47 left_p = 1; 48 c = *++p; 49 } 50 char pad = ' '; 51 if (c == ' ') 52 { 53 pad = c; 54 c = *p++; 55 } 56 if (c == '0') 57 { 58 pad = c; 59 c = *p++; 60 } 61 if (c >= '0' && c <= '9') 62 { 63 width = abtol (&p, 10); 64 c = *p; 65 } 66 else if (c == '*') 67 { 68 width = va_arg (ap, int); 69 c = *++p; 70 } 71 if (c == '.') 72 { 73 c = *++p; 74 if (c >= '0' && c <= '9') 75 { 76 precision = abtol (&p, 10); 77 c = *p; 78 } 79 else if (c == '*') 80 { 81 precision = va_arg (ap, int); 82 c = *++p; 83 } 84 } 85 if (c == 'l') 86 c = *++p; 87 if (c == 'l') 88 { 89 eputs ("vfprintf: skipping second: l\n"); 90 c = *++p; 91 } 92 switch (c) 93 { 94 case '%': 95 { 96 fputc (*p, f); 97 count++; 98 break; 99 } 100 case 'c': 101 { 102 char _c; 103 _c = va_arg (ap, long); 104 fputc (_c, f); 105 break; 106 } 107 case 'd': 108 case 'i': 109 case 'o': 110 case 'u': 111 case 'x': 112 case 'X': 113 { 114 long d = va_arg (ap, long); 115 int base = c == 'o' ? 8 : c == 'x' || c == 'X' ? 16 : 10; 116 char *s = ntoab (d, base, c != 'u' && c != 'x' && c != 'X'); 117 if (c == 'X') 118 strupr (s); 119 int length = strlen (s); 120 if (precision == -1) 121 precision = length; 122 if (!left_p) 123 { 124 while (width-- > precision) 125 { 126 fputc (pad, f); 127 count++; 128 } 129 while (precision > length) 130 { 131 fputc ('0', f); 132 precision--; 133 width--; 134 count++; 135 } 136 } 137 while (*s) 138 { 139 if (precision-- <= 0) 140 break; 141 width--; 142 fputc (*s++, f); 143 count++; 144 } 145 while (width > 0) 146 { 147 width--; 148 fputc (pad, f); 149 count++; 150 } 151 break; 152 } 153 case 's': 154 { 155 char *s = va_arg (ap, char *); 156 int length = strlen (s); 157 if (precision == -1) 158 precision = length; 159 if (!left_p) 160 { 161 while (width-- > precision) 162 { 163 fputc (pad, f); 164 count++; 165 } 166 while (precision > length) 167 { 168 fputc (' ', f); 169 precision--; 170 width--; 171 count++; 172 } 173 } 174 while (*s) 175 { 176 if (precision-- <= 0) 177 break; 178 width--; 179 fputc (*s++, f); 180 count++; 181 } 182 while (width > 0) 183 { 184 width--; 185 fputc (pad, f); 186 count++; 187 } 188 break; 189 } 190 case 'f': 191 case 'e': 192 case 'E': 193 case 'g': 194 case 'G': 195 { 196 double d = va_arg8 (ap, double); 197 char *s = dtoab (d, 10, 1); 198 if (c == 'E' || c == 'G') 199 strupr (s); 200 int length = strlen (s); 201 if (precision == -1) 202 precision = length; 203 if (!left_p) 204 { 205 while (width-- > precision) 206 { 207 fputc (pad, f); 208 count++; 209 } 210 while (precision > length) 211 { 212 fputc (' ', f); 213 precision--; 214 width--; 215 count++; 216 } 217 } 218 while (*s) 219 { 220 if (precision-- <= 0) 221 break; 222 width--; 223 fputc (*s++, f); 224 count++; 225 } 226 while (width > 0) 227 { 228 width--; 229 fputc (pad, f); 230 count++; 231 } 232 break; 233 } 234 case 'n': 235 { 236 int *n = va_arg (ap, int *); 237 *n = count; 238 break; 239 } 240 default: 241 { 242 eputs ("vfprintf: not supported: %:"); 243 eputc (c); 244 eputs ("\n"); 245 p++; 246 } 247 } 248 p++; 249 } 250 va_end (ap); 251 return 0; 252 }