1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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*
fmtfmt(const char * as)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