1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #pragma prototyped 23 24 /* 25 * Glenn Fowler 26 * AT&T Research 27 * 28 * return printf(3) format signature given format string 29 * the format signature contains one char per format optionally preceded 30 * by the number of `*' args 31 * c char 32 * d double 33 * D long double 34 * f float 35 * h short 36 * i int 37 * j long long 38 * l long 39 * p void* 40 * s string 41 * t ptrdiff_t 42 * z size_t 43 * ? unknown 44 */ 45 46 #include <ast.h> 47 #include <ctype.h> 48 49 char* 50 fmtfmt(const char* as) 51 { 52 register char* s = (char*)as; 53 char* buf; 54 int i; 55 int c; 56 int a; 57 int q; 58 int x; 59 int t; 60 int m; 61 int n; 62 int z; 63 char formats[256]; 64 unsigned int extra[elementsof(formats)]; 65 66 z = 1; 67 i = m = 0; 68 for (;;) 69 { 70 switch (*s++) 71 { 72 case 0: 73 break; 74 case '%': 75 if (*s == '%') 76 continue; 77 n = 0; 78 a = 0; 79 q = 0; 80 t = '?'; 81 x = 0; 82 for (;;) 83 { 84 switch (c = *s++) 85 { 86 case 0: 87 s--; 88 break; 89 case '(': 90 q++; 91 continue; 92 case ')': 93 if (--q <= 0) 94 n = 0; 95 continue; 96 case '0': case '1': case '2': case '3': 97 case '4': case '5': case '6': case '7': 98 case '8': case '9': 99 n = n * 10 + (c - '0'); 100 continue; 101 case '$': 102 a = n; 103 n = 0; 104 continue; 105 case '*': 106 x++; 107 n = 0; 108 continue; 109 case 'h': 110 if (!q) 111 t = t == 'h' ? 'c' : 'h'; 112 continue; 113 case 'l': 114 if (!q) 115 t = t == 'l' ? 'j' : 'l'; 116 continue; 117 case 'j': 118 case 't': 119 case 'z': 120 if (!q) 121 t = c; 122 continue; 123 case 'c': 124 case 'p': 125 case 's': 126 if (!q) 127 { 128 t = c; 129 break; 130 } 131 continue; 132 case 'e': 133 case 'g': 134 if (!q) 135 { 136 switch (t) 137 { 138 case 'j': 139 t = 'D'; 140 break; 141 default: 142 t = 'd'; 143 break; 144 } 145 break; 146 } 147 continue; 148 case 'f': 149 if (!q) 150 { 151 switch (t) 152 { 153 case 'j': 154 t = 'D'; 155 break; 156 case 'l': 157 t = 'd'; 158 break; 159 default: 160 t = c; 161 break; 162 } 163 break; 164 } 165 continue; 166 default: 167 if (!q && isalpha(c)) 168 { 169 if (t == '?') 170 t = 'i'; 171 break; 172 } 173 n = 0; 174 continue; 175 } 176 break; 177 } 178 if (a) 179 i = a; 180 else 181 i++; 182 if (i < elementsof(formats)) 183 { 184 formats[i] = t; 185 if (extra[i] = x) 186 do z++; while (x /= 10); 187 if (m < i) 188 m = i; 189 } 190 continue; 191 default: 192 continue; 193 } 194 break; 195 } 196 s = buf = fmtbuf(m + z); 197 for (i = 1; i <= m; i++) 198 { 199 if (extra[i]) 200 s += sfsprintf(s, 10, "%d", extra[m]); 201 *s++ = formats[i]; 202 } 203 *s = 0; 204 return buf; 205 } 206