1*86d7f5d3SJohn Marino /* #ifdef-format output routines for GNU DIFF.
2*86d7f5d3SJohn Marino Copyright (C) 1989, 1991, 1992, 1993, 1994, 1998 Free Software Foundation, Inc.
3*86d7f5d3SJohn Marino
4*86d7f5d3SJohn Marino This file is part of GNU DIFF.
5*86d7f5d3SJohn Marino
6*86d7f5d3SJohn Marino GNU DIFF is distributed in the hope that it will be useful,
7*86d7f5d3SJohn Marino but WITHOUT ANY WARRANTY. No author or distributor
8*86d7f5d3SJohn Marino accepts responsibility to anyone for the consequences of using it
9*86d7f5d3SJohn Marino or for whether it serves any particular purpose or works at all,
10*86d7f5d3SJohn Marino unless he says so in writing. Refer to the GNU DIFF General Public
11*86d7f5d3SJohn Marino License for full details.
12*86d7f5d3SJohn Marino
13*86d7f5d3SJohn Marino Everyone is granted permission to copy, modify and redistribute
14*86d7f5d3SJohn Marino GNU DIFF, but only under the conditions described in the
15*86d7f5d3SJohn Marino GNU DIFF General Public License. A copy of this license is
16*86d7f5d3SJohn Marino supposed to have been given to you along with GNU DIFF so you
17*86d7f5d3SJohn Marino can know your rights and responsibilities. It should be in a
18*86d7f5d3SJohn Marino file named COPYING. Among other things, the copyright notice
19*86d7f5d3SJohn Marino and this notice must be preserved on all copies. */
20*86d7f5d3SJohn Marino
21*86d7f5d3SJohn Marino
22*86d7f5d3SJohn Marino #include "diff.h"
23*86d7f5d3SJohn Marino
24*86d7f5d3SJohn Marino struct group
25*86d7f5d3SJohn Marino {
26*86d7f5d3SJohn Marino struct file_data const *file;
27*86d7f5d3SJohn Marino int from, upto; /* start and limit lines for this group of lines */
28*86d7f5d3SJohn Marino };
29*86d7f5d3SJohn Marino
30*86d7f5d3SJohn Marino static char *format_group PARAMS((int, char *, int, struct group const *));
31*86d7f5d3SJohn Marino static char *scan_char_literal PARAMS((char *, int *));
32*86d7f5d3SJohn Marino static char *scan_printf_spec PARAMS((char *));
33*86d7f5d3SJohn Marino static int groups_letter_value PARAMS((struct group const *, int));
34*86d7f5d3SJohn Marino static void format_ifdef PARAMS((char *, int, int, int, int));
35*86d7f5d3SJohn Marino static void print_ifdef_hunk PARAMS((struct change *));
36*86d7f5d3SJohn Marino static void print_ifdef_lines PARAMS((int, char *, struct group const *));
37*86d7f5d3SJohn Marino
38*86d7f5d3SJohn Marino static int next_line;
39*86d7f5d3SJohn Marino
40*86d7f5d3SJohn Marino /* Print the edit-script SCRIPT as a merged #ifdef file. */
41*86d7f5d3SJohn Marino
42*86d7f5d3SJohn Marino void
print_ifdef_script(script)43*86d7f5d3SJohn Marino print_ifdef_script (script)
44*86d7f5d3SJohn Marino struct change *script;
45*86d7f5d3SJohn Marino {
46*86d7f5d3SJohn Marino next_line = - files[0].prefix_lines;
47*86d7f5d3SJohn Marino print_script (script, find_change, print_ifdef_hunk);
48*86d7f5d3SJohn Marino if (next_line < files[0].valid_lines)
49*86d7f5d3SJohn Marino {
50*86d7f5d3SJohn Marino begin_output ();
51*86d7f5d3SJohn Marino format_ifdef (group_format[UNCHANGED], next_line, files[0].valid_lines,
52*86d7f5d3SJohn Marino next_line - files[0].valid_lines + files[1].valid_lines,
53*86d7f5d3SJohn Marino files[1].valid_lines);
54*86d7f5d3SJohn Marino }
55*86d7f5d3SJohn Marino }
56*86d7f5d3SJohn Marino
57*86d7f5d3SJohn Marino /* Print a hunk of an ifdef diff.
58*86d7f5d3SJohn Marino This is a contiguous portion of a complete edit script,
59*86d7f5d3SJohn Marino describing changes in consecutive lines. */
60*86d7f5d3SJohn Marino
61*86d7f5d3SJohn Marino static void
print_ifdef_hunk(hunk)62*86d7f5d3SJohn Marino print_ifdef_hunk (hunk)
63*86d7f5d3SJohn Marino struct change *hunk;
64*86d7f5d3SJohn Marino {
65*86d7f5d3SJohn Marino int first0, last0, first1, last1, deletes, inserts;
66*86d7f5d3SJohn Marino char *format;
67*86d7f5d3SJohn Marino
68*86d7f5d3SJohn Marino /* Determine range of line numbers involved in each file. */
69*86d7f5d3SJohn Marino analyze_hunk (hunk, &first0, &last0, &first1, &last1, &deletes, &inserts);
70*86d7f5d3SJohn Marino if (inserts)
71*86d7f5d3SJohn Marino format = deletes ? group_format[CHANGED] : group_format[NEW];
72*86d7f5d3SJohn Marino else if (deletes)
73*86d7f5d3SJohn Marino format = group_format[OLD];
74*86d7f5d3SJohn Marino else
75*86d7f5d3SJohn Marino return;
76*86d7f5d3SJohn Marino
77*86d7f5d3SJohn Marino begin_output ();
78*86d7f5d3SJohn Marino
79*86d7f5d3SJohn Marino /* Print lines up to this change. */
80*86d7f5d3SJohn Marino if (next_line < first0)
81*86d7f5d3SJohn Marino format_ifdef (group_format[UNCHANGED], next_line, first0,
82*86d7f5d3SJohn Marino next_line - first0 + first1, first1);
83*86d7f5d3SJohn Marino
84*86d7f5d3SJohn Marino /* Print this change. */
85*86d7f5d3SJohn Marino next_line = last0 + 1;
86*86d7f5d3SJohn Marino format_ifdef (format, first0, next_line, first1, last1 + 1);
87*86d7f5d3SJohn Marino }
88*86d7f5d3SJohn Marino
89*86d7f5d3SJohn Marino /* Print a set of lines according to FORMAT.
90*86d7f5d3SJohn Marino Lines BEG0 up to END0 are from the first file;
91*86d7f5d3SJohn Marino lines BEG1 up to END1 are from the second file. */
92*86d7f5d3SJohn Marino
93*86d7f5d3SJohn Marino static void
format_ifdef(format,beg0,end0,beg1,end1)94*86d7f5d3SJohn Marino format_ifdef (format, beg0, end0, beg1, end1)
95*86d7f5d3SJohn Marino char *format;
96*86d7f5d3SJohn Marino int beg0, end0, beg1, end1;
97*86d7f5d3SJohn Marino {
98*86d7f5d3SJohn Marino struct group groups[2];
99*86d7f5d3SJohn Marino
100*86d7f5d3SJohn Marino groups[0].file = &files[0];
101*86d7f5d3SJohn Marino groups[0].from = beg0;
102*86d7f5d3SJohn Marino groups[0].upto = end0;
103*86d7f5d3SJohn Marino groups[1].file = &files[1];
104*86d7f5d3SJohn Marino groups[1].from = beg1;
105*86d7f5d3SJohn Marino groups[1].upto = end1;
106*86d7f5d3SJohn Marino format_group (1, format, '\0', groups);
107*86d7f5d3SJohn Marino }
108*86d7f5d3SJohn Marino
109*86d7f5d3SJohn Marino /* If DOIT is non-zero, output a set of lines according to FORMAT.
110*86d7f5d3SJohn Marino The format ends at the first free instance of ENDCHAR.
111*86d7f5d3SJohn Marino Yield the address of the terminating character.
112*86d7f5d3SJohn Marino GROUPS specifies which lines to print.
113*86d7f5d3SJohn Marino If OUT is zero, do not actually print anything; just scan the format. */
114*86d7f5d3SJohn Marino
115*86d7f5d3SJohn Marino static char *
format_group(doit,format,endchar,groups)116*86d7f5d3SJohn Marino format_group (doit, format, endchar, groups)
117*86d7f5d3SJohn Marino int doit;
118*86d7f5d3SJohn Marino char *format;
119*86d7f5d3SJohn Marino int endchar;
120*86d7f5d3SJohn Marino struct group const *groups;
121*86d7f5d3SJohn Marino {
122*86d7f5d3SJohn Marino register char c;
123*86d7f5d3SJohn Marino register char *f = format;
124*86d7f5d3SJohn Marino
125*86d7f5d3SJohn Marino while ((c = *f) != endchar && c != 0)
126*86d7f5d3SJohn Marino {
127*86d7f5d3SJohn Marino f++;
128*86d7f5d3SJohn Marino if (c == '%')
129*86d7f5d3SJohn Marino {
130*86d7f5d3SJohn Marino char *spec = f;
131*86d7f5d3SJohn Marino switch ((c = *f++))
132*86d7f5d3SJohn Marino {
133*86d7f5d3SJohn Marino case '%':
134*86d7f5d3SJohn Marino break;
135*86d7f5d3SJohn Marino
136*86d7f5d3SJohn Marino case '(':
137*86d7f5d3SJohn Marino /* Print if-then-else format e.g. `%(n=1?thenpart:elsepart)'. */
138*86d7f5d3SJohn Marino {
139*86d7f5d3SJohn Marino int i, value[2];
140*86d7f5d3SJohn Marino int thendoit, elsedoit;
141*86d7f5d3SJohn Marino
142*86d7f5d3SJohn Marino for (i = 0; i < 2; i++)
143*86d7f5d3SJohn Marino {
144*86d7f5d3SJohn Marino unsigned char f0 = f[0];
145*86d7f5d3SJohn Marino if (ISDIGIT (f0))
146*86d7f5d3SJohn Marino {
147*86d7f5d3SJohn Marino value[i] = atoi (f);
148*86d7f5d3SJohn Marino while (ISDIGIT ((unsigned char) *++f))
149*86d7f5d3SJohn Marino continue;
150*86d7f5d3SJohn Marino }
151*86d7f5d3SJohn Marino else
152*86d7f5d3SJohn Marino {
153*86d7f5d3SJohn Marino value[i] = groups_letter_value (groups, f0);
154*86d7f5d3SJohn Marino if (value[i] < 0)
155*86d7f5d3SJohn Marino goto bad_format;
156*86d7f5d3SJohn Marino f++;
157*86d7f5d3SJohn Marino }
158*86d7f5d3SJohn Marino if (*f++ != "=?"[i])
159*86d7f5d3SJohn Marino goto bad_format;
160*86d7f5d3SJohn Marino }
161*86d7f5d3SJohn Marino if (value[0] == value[1])
162*86d7f5d3SJohn Marino thendoit = doit, elsedoit = 0;
163*86d7f5d3SJohn Marino else
164*86d7f5d3SJohn Marino thendoit = 0, elsedoit = doit;
165*86d7f5d3SJohn Marino f = format_group (thendoit, f, ':', groups);
166*86d7f5d3SJohn Marino if (*f)
167*86d7f5d3SJohn Marino {
168*86d7f5d3SJohn Marino f = format_group (elsedoit, f + 1, ')', groups);
169*86d7f5d3SJohn Marino if (*f)
170*86d7f5d3SJohn Marino f++;
171*86d7f5d3SJohn Marino }
172*86d7f5d3SJohn Marino }
173*86d7f5d3SJohn Marino continue;
174*86d7f5d3SJohn Marino
175*86d7f5d3SJohn Marino case '<':
176*86d7f5d3SJohn Marino /* Print lines deleted from first file. */
177*86d7f5d3SJohn Marino print_ifdef_lines (doit, line_format[OLD], &groups[0]);
178*86d7f5d3SJohn Marino continue;
179*86d7f5d3SJohn Marino
180*86d7f5d3SJohn Marino case '=':
181*86d7f5d3SJohn Marino /* Print common lines. */
182*86d7f5d3SJohn Marino print_ifdef_lines (doit, line_format[UNCHANGED], &groups[0]);
183*86d7f5d3SJohn Marino continue;
184*86d7f5d3SJohn Marino
185*86d7f5d3SJohn Marino case '>':
186*86d7f5d3SJohn Marino /* Print lines inserted from second file. */
187*86d7f5d3SJohn Marino print_ifdef_lines (doit, line_format[NEW], &groups[1]);
188*86d7f5d3SJohn Marino continue;
189*86d7f5d3SJohn Marino
190*86d7f5d3SJohn Marino default:
191*86d7f5d3SJohn Marino {
192*86d7f5d3SJohn Marino int value;
193*86d7f5d3SJohn Marino char *speclim;
194*86d7f5d3SJohn Marino
195*86d7f5d3SJohn Marino f = scan_printf_spec (spec);
196*86d7f5d3SJohn Marino if (!f)
197*86d7f5d3SJohn Marino goto bad_format;
198*86d7f5d3SJohn Marino speclim = f;
199*86d7f5d3SJohn Marino c = *f++;
200*86d7f5d3SJohn Marino switch (c)
201*86d7f5d3SJohn Marino {
202*86d7f5d3SJohn Marino case '\'':
203*86d7f5d3SJohn Marino f = scan_char_literal (f, &value);
204*86d7f5d3SJohn Marino if (!f)
205*86d7f5d3SJohn Marino goto bad_format;
206*86d7f5d3SJohn Marino break;
207*86d7f5d3SJohn Marino
208*86d7f5d3SJohn Marino default:
209*86d7f5d3SJohn Marino value = groups_letter_value (groups, c);
210*86d7f5d3SJohn Marino if (value < 0)
211*86d7f5d3SJohn Marino goto bad_format;
212*86d7f5d3SJohn Marino break;
213*86d7f5d3SJohn Marino }
214*86d7f5d3SJohn Marino if (doit)
215*86d7f5d3SJohn Marino {
216*86d7f5d3SJohn Marino /* Temporarily replace e.g. "%3dnx" with "%3d\0x". */
217*86d7f5d3SJohn Marino *speclim = 0;
218*86d7f5d3SJohn Marino printf_output (spec - 1, value);
219*86d7f5d3SJohn Marino /* Undo the temporary replacement. */
220*86d7f5d3SJohn Marino *speclim = c;
221*86d7f5d3SJohn Marino }
222*86d7f5d3SJohn Marino }
223*86d7f5d3SJohn Marino continue;
224*86d7f5d3SJohn Marino
225*86d7f5d3SJohn Marino bad_format:
226*86d7f5d3SJohn Marino c = '%';
227*86d7f5d3SJohn Marino f = spec;
228*86d7f5d3SJohn Marino break;
229*86d7f5d3SJohn Marino }
230*86d7f5d3SJohn Marino }
231*86d7f5d3SJohn Marino if (doit)
232*86d7f5d3SJohn Marino {
233*86d7f5d3SJohn Marino /* Don't take the address of a register variable. */
234*86d7f5d3SJohn Marino char cc = c;
235*86d7f5d3SJohn Marino write_output (&cc, 1);
236*86d7f5d3SJohn Marino }
237*86d7f5d3SJohn Marino }
238*86d7f5d3SJohn Marino return f;
239*86d7f5d3SJohn Marino }
240*86d7f5d3SJohn Marino
241*86d7f5d3SJohn Marino /* For the line group pair G, return the number corresponding to LETTER.
242*86d7f5d3SJohn Marino Return -1 if LETTER is not a group format letter. */
243*86d7f5d3SJohn Marino static int
groups_letter_value(g,letter)244*86d7f5d3SJohn Marino groups_letter_value (g, letter)
245*86d7f5d3SJohn Marino struct group const *g;
246*86d7f5d3SJohn Marino int letter;
247*86d7f5d3SJohn Marino {
248*86d7f5d3SJohn Marino if (ISUPPER (letter))
249*86d7f5d3SJohn Marino {
250*86d7f5d3SJohn Marino g++;
251*86d7f5d3SJohn Marino letter = tolower (letter);
252*86d7f5d3SJohn Marino }
253*86d7f5d3SJohn Marino switch (letter)
254*86d7f5d3SJohn Marino {
255*86d7f5d3SJohn Marino case 'e': return translate_line_number (g->file, g->from) - 1;
256*86d7f5d3SJohn Marino case 'f': return translate_line_number (g->file, g->from);
257*86d7f5d3SJohn Marino case 'l': return translate_line_number (g->file, g->upto) - 1;
258*86d7f5d3SJohn Marino case 'm': return translate_line_number (g->file, g->upto);
259*86d7f5d3SJohn Marino case 'n': return g->upto - g->from;
260*86d7f5d3SJohn Marino default: return -1;
261*86d7f5d3SJohn Marino }
262*86d7f5d3SJohn Marino }
263*86d7f5d3SJohn Marino
264*86d7f5d3SJohn Marino /* Output using FORMAT to print the line group GROUP.
265*86d7f5d3SJohn Marino But do nothing if DOIT is zero. */
266*86d7f5d3SJohn Marino static void
print_ifdef_lines(doit,format,group)267*86d7f5d3SJohn Marino print_ifdef_lines (doit, format, group)
268*86d7f5d3SJohn Marino int doit;
269*86d7f5d3SJohn Marino char *format;
270*86d7f5d3SJohn Marino struct group const *group;
271*86d7f5d3SJohn Marino {
272*86d7f5d3SJohn Marino struct file_data const *file = group->file;
273*86d7f5d3SJohn Marino char const * const *linbuf = file->linbuf;
274*86d7f5d3SJohn Marino int from = group->from, upto = group->upto;
275*86d7f5d3SJohn Marino
276*86d7f5d3SJohn Marino if (!doit)
277*86d7f5d3SJohn Marino return;
278*86d7f5d3SJohn Marino
279*86d7f5d3SJohn Marino /* If possible, use a single fwrite; it's faster. */
280*86d7f5d3SJohn Marino if (!tab_expand_flag && format[0] == '%')
281*86d7f5d3SJohn Marino {
282*86d7f5d3SJohn Marino if (format[1] == 'l' && format[2] == '\n' && !format[3])
283*86d7f5d3SJohn Marino {
284*86d7f5d3SJohn Marino write_output (linbuf[from],
285*86d7f5d3SJohn Marino (linbuf[upto] + (linbuf[upto][-1] != '\n')
286*86d7f5d3SJohn Marino - linbuf[from]));
287*86d7f5d3SJohn Marino return;
288*86d7f5d3SJohn Marino }
289*86d7f5d3SJohn Marino if (format[1] == 'L' && !format[2])
290*86d7f5d3SJohn Marino {
291*86d7f5d3SJohn Marino write_output (linbuf[from],
292*86d7f5d3SJohn Marino linbuf[upto] - linbuf[from]);
293*86d7f5d3SJohn Marino return;
294*86d7f5d3SJohn Marino }
295*86d7f5d3SJohn Marino }
296*86d7f5d3SJohn Marino
297*86d7f5d3SJohn Marino for (; from < upto; from++)
298*86d7f5d3SJohn Marino {
299*86d7f5d3SJohn Marino register char c;
300*86d7f5d3SJohn Marino register char *f = format;
301*86d7f5d3SJohn Marino char cc;
302*86d7f5d3SJohn Marino
303*86d7f5d3SJohn Marino while ((c = *f++) != 0)
304*86d7f5d3SJohn Marino {
305*86d7f5d3SJohn Marino if (c == '%')
306*86d7f5d3SJohn Marino {
307*86d7f5d3SJohn Marino char *spec = f;
308*86d7f5d3SJohn Marino switch ((c = *f++))
309*86d7f5d3SJohn Marino {
310*86d7f5d3SJohn Marino case '%':
311*86d7f5d3SJohn Marino break;
312*86d7f5d3SJohn Marino
313*86d7f5d3SJohn Marino case 'l':
314*86d7f5d3SJohn Marino output_1_line (linbuf[from],
315*86d7f5d3SJohn Marino linbuf[from + 1]
316*86d7f5d3SJohn Marino - (linbuf[from + 1][-1] == '\n'), 0, 0);
317*86d7f5d3SJohn Marino continue;
318*86d7f5d3SJohn Marino
319*86d7f5d3SJohn Marino case 'L':
320*86d7f5d3SJohn Marino output_1_line (linbuf[from], linbuf[from + 1], 0, 0);
321*86d7f5d3SJohn Marino continue;
322*86d7f5d3SJohn Marino
323*86d7f5d3SJohn Marino default:
324*86d7f5d3SJohn Marino {
325*86d7f5d3SJohn Marino int value;
326*86d7f5d3SJohn Marino char *speclim;
327*86d7f5d3SJohn Marino
328*86d7f5d3SJohn Marino f = scan_printf_spec (spec);
329*86d7f5d3SJohn Marino if (!f)
330*86d7f5d3SJohn Marino goto bad_format;
331*86d7f5d3SJohn Marino speclim = f;
332*86d7f5d3SJohn Marino c = *f++;
333*86d7f5d3SJohn Marino switch (c)
334*86d7f5d3SJohn Marino {
335*86d7f5d3SJohn Marino case '\'':
336*86d7f5d3SJohn Marino f = scan_char_literal (f, &value);
337*86d7f5d3SJohn Marino if (!f)
338*86d7f5d3SJohn Marino goto bad_format;
339*86d7f5d3SJohn Marino break;
340*86d7f5d3SJohn Marino
341*86d7f5d3SJohn Marino case 'n':
342*86d7f5d3SJohn Marino value = translate_line_number (file, from);
343*86d7f5d3SJohn Marino break;
344*86d7f5d3SJohn Marino
345*86d7f5d3SJohn Marino default:
346*86d7f5d3SJohn Marino goto bad_format;
347*86d7f5d3SJohn Marino }
348*86d7f5d3SJohn Marino /* Temporarily replace e.g. "%3dnx" with "%3d\0x". */
349*86d7f5d3SJohn Marino *speclim = 0;
350*86d7f5d3SJohn Marino printf_output (spec - 1, value);
351*86d7f5d3SJohn Marino /* Undo the temporary replacement. */
352*86d7f5d3SJohn Marino *speclim = c;
353*86d7f5d3SJohn Marino }
354*86d7f5d3SJohn Marino continue;
355*86d7f5d3SJohn Marino
356*86d7f5d3SJohn Marino bad_format:
357*86d7f5d3SJohn Marino c = '%';
358*86d7f5d3SJohn Marino f = spec;
359*86d7f5d3SJohn Marino break;
360*86d7f5d3SJohn Marino }
361*86d7f5d3SJohn Marino }
362*86d7f5d3SJohn Marino
363*86d7f5d3SJohn Marino /* Don't take the address of a register variable. */
364*86d7f5d3SJohn Marino cc = c;
365*86d7f5d3SJohn Marino write_output (&cc, 1);
366*86d7f5d3SJohn Marino }
367*86d7f5d3SJohn Marino }
368*86d7f5d3SJohn Marino }
369*86d7f5d3SJohn Marino
370*86d7f5d3SJohn Marino /* Scan the character literal represented in the string LIT; LIT points just
371*86d7f5d3SJohn Marino after the initial apostrophe. Put the literal's value into *INTPTR.
372*86d7f5d3SJohn Marino Yield the address of the first character after the closing apostrophe,
373*86d7f5d3SJohn Marino or zero if the literal is ill-formed. */
374*86d7f5d3SJohn Marino static char *
scan_char_literal(lit,intptr)375*86d7f5d3SJohn Marino scan_char_literal (lit, intptr)
376*86d7f5d3SJohn Marino char *lit;
377*86d7f5d3SJohn Marino int *intptr;
378*86d7f5d3SJohn Marino {
379*86d7f5d3SJohn Marino register char *p = lit;
380*86d7f5d3SJohn Marino int value, digits;
381*86d7f5d3SJohn Marino char c = *p++;
382*86d7f5d3SJohn Marino
383*86d7f5d3SJohn Marino switch (c)
384*86d7f5d3SJohn Marino {
385*86d7f5d3SJohn Marino case 0:
386*86d7f5d3SJohn Marino case '\'':
387*86d7f5d3SJohn Marino return 0;
388*86d7f5d3SJohn Marino
389*86d7f5d3SJohn Marino case '\\':
390*86d7f5d3SJohn Marino value = 0;
391*86d7f5d3SJohn Marino while ((c = *p++) != '\'')
392*86d7f5d3SJohn Marino {
393*86d7f5d3SJohn Marino unsigned digit = c - '0';
394*86d7f5d3SJohn Marino if (8 <= digit)
395*86d7f5d3SJohn Marino return 0;
396*86d7f5d3SJohn Marino value = 8 * value + digit;
397*86d7f5d3SJohn Marino }
398*86d7f5d3SJohn Marino digits = p - lit - 2;
399*86d7f5d3SJohn Marino if (! (1 <= digits && digits <= 3))
400*86d7f5d3SJohn Marino return 0;
401*86d7f5d3SJohn Marino break;
402*86d7f5d3SJohn Marino
403*86d7f5d3SJohn Marino default:
404*86d7f5d3SJohn Marino value = c;
405*86d7f5d3SJohn Marino if (*p++ != '\'')
406*86d7f5d3SJohn Marino return 0;
407*86d7f5d3SJohn Marino break;
408*86d7f5d3SJohn Marino }
409*86d7f5d3SJohn Marino *intptr = value;
410*86d7f5d3SJohn Marino return p;
411*86d7f5d3SJohn Marino }
412*86d7f5d3SJohn Marino
413*86d7f5d3SJohn Marino /* Scan optional printf-style SPEC of the form `-*[0-9]*(.[0-9]*)?[cdoxX]'.
414*86d7f5d3SJohn Marino Return the address of the character following SPEC, or zero if failure. */
415*86d7f5d3SJohn Marino static char *
scan_printf_spec(spec)416*86d7f5d3SJohn Marino scan_printf_spec (spec)
417*86d7f5d3SJohn Marino register char *spec;
418*86d7f5d3SJohn Marino {
419*86d7f5d3SJohn Marino register unsigned char c;
420*86d7f5d3SJohn Marino
421*86d7f5d3SJohn Marino while ((c = *spec++) == '-')
422*86d7f5d3SJohn Marino continue;
423*86d7f5d3SJohn Marino while (ISDIGIT (c))
424*86d7f5d3SJohn Marino c = *spec++;
425*86d7f5d3SJohn Marino if (c == '.')
426*86d7f5d3SJohn Marino while (ISDIGIT (c = *spec++))
427*86d7f5d3SJohn Marino continue;
428*86d7f5d3SJohn Marino switch (c)
429*86d7f5d3SJohn Marino {
430*86d7f5d3SJohn Marino case 'c': case 'd': case 'o': case 'x': case 'X':
431*86d7f5d3SJohn Marino return spec;
432*86d7f5d3SJohn Marino
433*86d7f5d3SJohn Marino default:
434*86d7f5d3SJohn Marino return 0;
435*86d7f5d3SJohn Marino }
436*86d7f5d3SJohn Marino }
437