Subversion Repositories tendra.SVN

Rev

Rev 5 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5 Rev 6
Line -... Line 1...
-
 
1
/*
-
 
2
 * Copyright (c) 2002-2006 The TenDRA Project <http://www.tendra.org/>.
-
 
3
 * All rights reserved.
-
 
4
 *
-
 
5
 * Redistribution and use in source and binary forms, with or without
-
 
6
 * modification, are permitted provided that the following conditions are met:
-
 
7
 *
-
 
8
 * 1. Redistributions of source code must retain the above copyright notice,
-
 
9
 *    this list of conditions and the following disclaimer.
-
 
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
-
 
11
 *    this list of conditions and the following disclaimer in the documentation
-
 
12
 *    and/or other materials provided with the distribution.
-
 
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
-
 
14
 *    may be used to endorse or promote products derived from this software
-
 
15
 *    without specific, prior written permission.
-
 
16
 *
-
 
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
-
 
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-
 
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-
 
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
-
 
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-
 
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-
 
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-
 
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-
 
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-
 
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-
 
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 
28
 *
-
 
29
 * $Id$
-
 
30
 */
1
/*
31
/*
2
    		 Crown Copyright (c) 1997
32
    		 Crown Copyright (c) 1997
3
    
33
 
4
    This TenDRA(r) Computer Program is subject to Copyright
34
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
35
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
36
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
37
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
38
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
39
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
40
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
41
    shall be deemed to be acceptance of the following conditions:-
12
    
42
 
13
        (1) Its Recipients shall ensure that this Notice is
43
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
44
        reproduced upon any copies or amended versions of it;
15
    
45
 
16
        (2) Any amended version of it shall be clearly marked to
46
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
47
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
48
        for the relevant amendment or amendments;
19
    
49
 
20
        (3) Its onward transfer from a recipient to another
50
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
51
        party shall be deemed to be that party's acceptance of
22
        these conditions;
52
        these conditions;
23
    
53
 
24
        (4) DERA gives no warranty or assurance as to its
54
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
55
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
56
        no liability whatsoever in relation to any use to which
27
        it may be put.
57
        it may be put.
28
*/
58
*/
Line 52... Line 82...
52
 
82
 
53
    These values are used to indicate the various flags, field widths and
83
    These values are used to indicate the various flags, field widths and
54
    precision used to modify printf and scanf format strings.
84
    precision used to modify printf and scanf format strings.
55
*/
85
*/
56
 
86
 
57
#define PRINTF_NONE		( ( unsigned ) 0x0000 )
87
#define PRINTF_NONE		((unsigned)0x0000)
58
#define PRINTF_THOUSAND		( ( unsigned ) 0x0001 )
88
#define PRINTF_THOUSAND		((unsigned)0x0001)
59
#define PRINTF_LEFT		( ( unsigned ) 0x0002 )
89
#define PRINTF_LEFT		((unsigned)0x0002)
60
#define PRINTF_SIGN		( ( unsigned ) 0x0004 )
90
#define PRINTF_SIGN		((unsigned)0x0004)
61
#define PRINTF_SPACE		( ( unsigned ) 0x0008 )
91
#define PRINTF_SPACE		((unsigned)0x0008)
62
#define PRINTF_ALT		( ( unsigned ) 0x0010 )
92
#define PRINTF_ALT		((unsigned)0x0010)
63
#define PRINTF_ZERO		( ( unsigned ) 0x0020 )
93
#define PRINTF_ZERO		((unsigned)0x0020)
64
#define PRINTF_WIDTH		( ( unsigned ) 0x0040 )
94
#define PRINTF_WIDTH		((unsigned)0x0040)
65
#define PRINTF_PREC		( ( unsigned ) 0x0080 )
95
#define PRINTF_PREC		((unsigned)0x0080)
66
#define PRINTF_ERROR		( ( unsigned ) 0x0100 )
96
#define PRINTF_ERROR		((unsigned)0x0100)
67
#define PRINTF_FLAGS		( ( unsigned ) 0x003f )
97
#define PRINTF_FLAGS		((unsigned)0x003f)
68
#define PRINTF_ARITH		( ( unsigned ) 0x003d )
98
#define PRINTF_ARITH		((unsigned)0x003d)
69
 
99
 
70
 
100
 
71
/*
101
/*
72
    SKIP A NUMBER OF DIGITS FROM A STRING
102
    SKIP A NUMBER OF DIGITS FROM A STRING
73
 
103
 
74
    This routine skips a number of decimal digits from the string str.
104
    This routine skips a number of decimal digits from the string str.
75
    The first character and its character type are given by c and pc.
105
    The first character and its character type are given by c and pc.
76
    The routine returns the first non-digit character, assigning the
106
    The routine returns the first non-digit character, assigning the
77
    value read (or UINT_MAX if an overflow occurs) into pn.
107
    value read (or UINT_MAX if an overflow occurs) into pn.
78
*/
108
*/
79
 
109
 
80
static unsigned long read_width
110
static unsigned long
81
    PROTO_N ( ( str, c, pc, pn ) )
-
 
82
    PROTO_T ( STRING str X unsigned long c X int *pc X unsigned *pn )
111
read_width(STRING str, unsigned long c, int *pc, unsigned *pn)
83
{
112
{
84
    unsigned n = 0 ;
113
	unsigned n = 0;
85
    unsigned m = 0 ;
114
	unsigned m = 0;
86
    int overflow = 0 ;
115
	int overflow = 0;
87
    while ( *pc == CHAR_SIMPLE && ( c >= char_zero && c <= char_nine ) ) {
116
	while (*pc == CHAR_SIMPLE && (c >= char_zero && c <= char_nine)) {
88
	n = 10 * n + ( unsigned ) ( c - char_zero ) ;
117
		n = 10 * n + (unsigned)(c - char_zero);
-
 
118
		if (n < m) {
89
	if ( n < m ) overflow = 1 ;
119
			overflow = 1;
-
 
120
		}
90
	m = n ;
121
		m = n;
91
	c = get_string_char ( str, pc ) ;
122
		c = get_string_char(str, pc);
92
    }
123
	}
93
    if ( overflow ) n = UINT_MAX ;
124
	if (overflow) {
-
 
125
		n = UINT_MAX;
-
 
126
	}
94
    *pn = n ;
127
	*pn = n;
95
    return ( c ) ;
128
	return (c);
96
}
129
}
97
 
130
 
98
 
131
 
99
/*
132
/*
100
    READ A PRINTF ARGUMENT NUMBER
133
    READ A PRINTF ARGUMENT NUMBER
101
 
134
 
Line 104... Line 137...
104
    used to indicate the nth, as opposed to the next, argument.  This
137
    used to indicate the nth, as opposed to the next, argument.  This
105
    routine checks for such sequences in the string str, returning n.
138
    routine checks for such sequences in the string str, returning n.
106
    margs gives the maximum value allowed for n, if n exceeds this value
139
    margs gives the maximum value allowed for n, if n exceeds this value
107
    then it UINT_MAX is returned.  A value of 0 is returned if str does
140
    then it UINT_MAX is returned.  A value of 0 is returned if str does
108
    not have this form (note that the arguments are numbered from 1).
141
    not have this form (note that the arguments are numbered from 1).
109
*/
142
*/
110
 
143
 
111
static unsigned read_arg_no
144
static unsigned
112
    PROTO_N ( ( str, margs ) )
-
 
113
    PROTO_T ( STRING str X unsigned margs )
145
read_arg_no(STRING str, unsigned margs)
114
{
146
{
115
    unsigned long tok = DEREF_ulong ( str_simple_tok ( str ) ) ;
147
	unsigned long tok = DEREF_ulong(str_simple_tok(str));
116
    int ch = CHAR_SIMPLE ;
148
	int ch = CHAR_SIMPLE;
117
    unsigned long c = get_string_char ( str, &ch ) ;
149
	unsigned long c = get_string_char(str, &ch);
118
    if ( ch == CHAR_SIMPLE && ( c >= char_zero && c <= char_nine ) ) {
150
	if (ch == CHAR_SIMPLE && (c >= char_zero && c <= char_nine)) {
119
	unsigned n = 0 ;
151
		unsigned n = 0;
120
	c = read_width ( str, c, &ch, &n ) ;
152
		c = read_width(str, c, &ch, &n);
121
	if ( ch == CHAR_SIMPLE && c == char_dollar ) {
153
		if (ch == CHAR_SIMPLE && c == char_dollar) {
122
	    if ( n > margs ) {
154
			if (n > margs) {
123
		/* Argument number out of range */
155
				/* Argument number out of range */
124
		report ( crt_loc, ERR_printf_arg_large ( n ) ) ;
156
				report(crt_loc, ERR_printf_arg_large(n));
125
		n = UINT_MAX ;
157
				n = UINT_MAX;
126
	    }
158
			}
127
	    if ( n == 0 ) {
159
			if (n == 0) {
128
		/* Can't have argument zero */
160
				/* Can't have argument zero */
129
		report ( crt_loc, ERR_printf_arg_zero () ) ;
161
				report(crt_loc, ERR_printf_arg_zero());
130
		n = 1 ;
162
				n = 1;
131
	    }
163
			}
132
	    return ( n ) ;
164
			return (n);
133
	}
165
		}
134
    }
166
	}
135
    COPY_ulong ( str_simple_tok ( str ), tok ) ;
167
	COPY_ulong(str_simple_tok(str), tok);
136
    return ( 0 ) ;
168
	return (0);
137
}
169
}
138
 
170
 
139
 
171
 
140
/*
172
/*
141
    CHECK A PRINTF OR SCANF FORMAT STRING
173
    CHECK A PRINTF OR SCANF FORMAT STRING
142
 
174
 
143
    This routine combines a printf or scanf format string corresponding to
175
    This routine combines a printf or scanf format string corresponding to
144
    the type n, modified by the type modifier m.  flags gives any invalid
176
    the type n, modified by the type modifier m.  flags gives any invalid
145
    format flags.
177
    format flags.
146
*/
178
*/
147
 
179
 
148
static BUILTIN_TYPE check_format
180
static BUILTIN_TYPE
149
    PROTO_N ( ( s, n, m, flags ) )
-
 
150
    PROTO_T ( string s X BUILTIN_TYPE n X BUILTIN_TYPE m X unsigned flags )
181
check_format(string s, BUILTIN_TYPE n, BUILTIN_TYPE m, unsigned flags)
151
{
182
{
152
    switch ( m ) {
183
	switch (m) {
153
	case ntype_sshort : {
184
	case ntype_sshort:
154
	    /* 'h' modifier */
185
		/* 'h' modifier */
155
	    switch ( n ) {
186
		switch (n) {
-
 
187
		case ntype_sint:
156
		case ntype_sint : n = ntype_sshort ; break ;
188
			n = ntype_sshort;
-
 
189
			break;
157
		case ntype_uint : n = ntype_ushort ; break ;
190
		case ntype_uint:
158
		default : flags |= PRINTF_ERROR ; break ;
191
			n = ntype_ushort;
159
	    }
192
			break;
-
 
193
		default:
-
 
194
			flags |= PRINTF_ERROR;
160
	    break ;
195
			break;
161
	}
196
		}
-
 
197
		break;
162
	case ntype_slong : {
198
	case ntype_slong:
163
	    /* 'l' modifier */
199
		/* 'l' modifier */
164
	    switch ( n ) {
200
		switch (n) {
-
 
201
		case ntype_char:
165
		case ntype_char : n = ntype_wchar_t ; break ;
202
			n = ntype_wchar_t;
-
 
203
			break;
166
		case ntype_uchar : n = ntype_none ; break ;
204
		case ntype_uchar:
-
 
205
			n = ntype_none;
-
 
206
			break;
-
 
207
		case ntype_sint:
167
		case ntype_sint : n = ntype_slong ; break ;
208
			n = ntype_slong;
-
 
209
			break;
-
 
210
		case ntype_uint:
168
		case ntype_uint : n = ntype_ulong ; break ;
211
			n = ntype_ulong;
-
 
212
			break;
-
 
213
		case ntype_float:
169
		case ntype_float : n = ntype_double ; break ;
214
			n = ntype_double;
-
 
215
			break;
-
 
216
		default:
170
		default : flags |= PRINTF_ERROR ; break ;
217
			flags |= PRINTF_ERROR;
-
 
218
			break;
171
	    }
219
		}
-
 
220
		break;
-
 
221
	case ntype_ldouble:
-
 
222
		/* 'L' modifier */
-
 
223
		switch (n) {
-
 
224
		case ntype_float:
-
 
225
			n = ntype_ldouble;
-
 
226
			break;
-
 
227
		case ntype_double:
-
 
228
			n = ntype_ldouble;
-
 
229
			break;
-
 
230
		default:
-
 
231
			flags |= PRINTF_ERROR;
172
	    break ;
232
			break;
-
 
233
		}
-
 
234
		break;
173
	}
235
	}
174
	case ntype_ldouble : {
-
 
175
	    /* 'L' modifier */
-
 
176
	    switch ( n ) {
-
 
177
		case ntype_float : n = ntype_ldouble ; break ;
-
 
178
		case ntype_double : n = ntype_ldouble ; break ;
-
 
179
		default : flags |= PRINTF_ERROR ; break ;
-
 
180
	    }
-
 
181
	    break ;
-
 
182
	}
236
 
183
    }
-
 
184
    if ( flags ) {
237
	if (flags) {
185
	if ( flags & PRINTF_ERROR ) {
238
		if (flags & PRINTF_ERROR) {
186
	    report ( crt_loc, ERR_printf_invalid ( s ) ) ;
239
			report(crt_loc, ERR_printf_invalid(s));
187
	    s [1] = s [2] ;
240
			s[1] = s[2];
188
	    s [2] = 0 ;
241
			s[2] = 0;
189
	}
242
		}
190
	if ( flags & PRINTF_FLAGS ) {
243
		if (flags & PRINTF_FLAGS) {
191
	    character t [8] ;
244
			character t[8];
192
	    string r = t ;
245
			string r = t;
193
	    if ( flags & PRINTF_THOUSAND ) *( r++ ) = char_single_quote ;
246
			if (flags & PRINTF_THOUSAND) {
-
 
247
				*(r++) = char_single_quote;
-
 
248
			}
194
	    if ( flags & PRINTF_LEFT ) *( r++ ) = char_minus ;
249
			if (flags & PRINTF_LEFT) {
-
 
250
				*(r++) = char_minus;
-
 
251
			}
195
	    if ( flags & PRINTF_SIGN ) *( r++ ) = char_plus ;
252
			if (flags & PRINTF_SIGN) {
-
 
253
				*(r++) = char_plus;
-
 
254
			}
196
	    if ( flags & PRINTF_SPACE ) *( r++ ) = char_space ;
255
			if (flags & PRINTF_SPACE) {
-
 
256
				*(r++) = char_space;
-
 
257
			}
197
	    if ( flags & PRINTF_ALT ) *( r++ ) = char_hash ;
258
			if (flags & PRINTF_ALT) {
-
 
259
				*(r++) = char_hash;
-
 
260
			}
198
	    if ( flags & PRINTF_ZERO ) *( r++ ) = char_zero ;
261
			if (flags & PRINTF_ZERO) {
-
 
262
				*(r++) = char_zero;
-
 
263
			}
199
	    *r = 0 ;
264
			*r = 0;
200
	    report ( crt_loc, ERR_printf_flags ( t, s ) ) ;
265
			report(crt_loc, ERR_printf_flags(t, s));
201
	}
266
		}
202
	if ( flags & PRINTF_WIDTH ) {
267
		if (flags & PRINTF_WIDTH) {
203
	    report ( crt_loc, ERR_printf_width ( s ) ) ;
268
			report(crt_loc, ERR_printf_width(s));
204
	}
269
		}
205
	if ( flags & PRINTF_PREC ) {
270
		if (flags & PRINTF_PREC) {
206
	    report ( crt_loc, ERR_printf_precision ( s ) ) ;
271
			report(crt_loc, ERR_printf_precision(s));
-
 
272
		}
207
	}
273
	}
208
    }
-
 
209
    return ( n ) ;
274
	return (n);
210
}
275
}
211
 
276
 
212
 
277
 
213
/*
278
/*
214
    SET AN ARGUMENT TYPE
279
    SET AN ARGUMENT TYPE
215
 
280
 
216
    This routine sets the nth argument of the list p to be t.  The elements
281
    This routine sets the nth argument of the list p to be t.  The elements
217
    of p are in reverse order and numbered from 1.  A zero value for n is
282
    of p are in reverse order and numbered from 1.  A zero value for n is
218
    equivalent to 'LENGTH_list ( p ) + 1'.  The state flag is used to keep
283
    equivalent to 'LENGTH_list ( p ) + 1'.  The state flag is used to keep
219
    track of whether numbered and unnumbered arguments are mixed.
284
    track of whether numbered and unnumbered arguments are mixed.
220
*/
285
*/
221
 
286
 
222
static LIST ( TYPE ) set_printf_arg
287
static LIST(TYPE)
223
    PROTO_N ( ( p, n, t, state ) )
-
 
224
    PROTO_T ( LIST ( TYPE ) p X unsigned n X TYPE t X int *state )
288
set_printf_arg(LIST(TYPE) p, unsigned n, TYPE t, int *state)
225
{
289
{
226
    if ( n == 0 ) {
290
	if (n == 0) {
227
	/* Simple case */
291
		/* Simple case */
228
	if ( *state == 2 ) {
292
		if (*state == 2) {
229
	    report ( crt_loc, ERR_printf_arg_mix () ) ;
293
			report(crt_loc, ERR_printf_arg_mix());
230
	    *state = 3 ;
294
			*state = 3;
-
 
295
		} else {
-
 
296
			*state = 1;
-
 
297
		}
-
 
298
		CONS_type(t, p, p);
231
	} else {
299
	} else {
232
	    *state = 1 ;
-
 
233
	}
-
 
234
	CONS_type ( t, p, p ) ;
-
 
235
    } else {
-
 
236
	unsigned m = UINT_MAX ;
300
		unsigned m = UINT_MAX;
237
	if ( *state == 1 ) {
301
		if (*state == 1) {
238
	    report ( crt_loc, ERR_printf_arg_mix () ) ;
302
			report(crt_loc, ERR_printf_arg_mix());
239
	    *state = 3 ;
303
			*state = 3;
240
	} else {
304
		} else {
241
	    *state = 2 ;
305
			*state = 2;
242
	}
306
		}
243
	if ( n != m ) {
307
		if (n != m) {
244
	    /* Valid argument number */
308
			/* Valid argument number */
245
	    TYPE s ;
309
			TYPE s;
246
	    LIST ( TYPE ) q ;
310
			LIST(TYPE) q;
247
	    m = LENGTH_list ( p ) ;
311
			m = LENGTH_list(p);
248
	    while ( m < n ) {
312
			while (m < n) {
249
		/* Add extra arguments if necessary */
313
				/* Add extra arguments if necessary */
250
		CONS_type ( NULL_type, p, p ) ;
314
				CONS_type(NULL_type, p, p);
251
		m++ ;
315
				m++;
252
	    }
316
			}
253
	    q = p ;
317
			q = p;
254
	    while ( m > n ) {
318
			while (m > n) {
255
		/* Scan to nth argument */
319
				/* Scan to nth argument */
256
		q = TAIL_list ( q ) ;
320
				q = TAIL_list(q);
257
		m-- ;
321
				m--;
258
	    }
322
			}
259
	    s = DEREF_type ( HEAD_list ( q ) ) ;
323
			s = DEREF_type(HEAD_list(q));
260
	    if ( !IS_NULL_type ( s ) && !EQ_type ( s, t ) ) {
324
			if (!IS_NULL_type(s) && !EQ_type(s, t)) {
261
		/* Check for compatibility with previous type */
325
				/* Check for compatibility with previous type */
262
		ERROR err = NULL_err ;
326
				ERROR err = NULL_err;
263
		t = check_compatible ( s, t, 1, &err, 1 ) ;
327
				t = check_compatible(s, t, 1, &err, 1);
264
		if ( !IS_NULL_err ( err ) ) {
328
				if (!IS_NULL_err(err)) {
265
		    err = set_severity ( err, OPT_whatever, 0 ) ;
329
					err = set_severity(err, OPT_whatever, 0);
266
		    err = concat_error ( err, ERR_printf_arg_compat ( n ) ) ;
330
					err = concat_error(err, ERR_printf_arg_compat(n));
267
		    report ( crt_loc, err ) ;
331
					report(crt_loc, err);
-
 
332
				}
-
 
333
			}
-
 
334
			COPY_type(HEAD_list(q), t);
268
		}
335
		}
269
	    }
-
 
270
	    COPY_type ( HEAD_list ( q ), t ) ;
-
 
271
	}
336
	}
272
    }
-
 
273
    return ( p ) ;
337
	return (p);
274
}
338
}
275
 
339
 
276
 
340
 
277
/*
341
/*
278
    PRINTF AND SCANF ARGUMENT TYPES
342
    PRINTF AND SCANF ARGUMENT TYPES
279
 
343
 
280
    These variables give those printf and scanf argument types which are
344
    These variables give those printf and scanf argument types which are
281
    not built-in types or pointers to built-in types.
345
    not built-in types or pointers to built-in types.
282
*/
346
*/
283
 
347
 
284
static TYPE ptr_const_char = NULL_type ;
348
static TYPE ptr_const_char = NULL_type;
285
static TYPE ptr_const_wchar_t = NULL_type ;
349
static TYPE ptr_const_wchar_t = NULL_type;
286
static TYPE ptr_ptr_void = NULL_type ;
350
static TYPE ptr_ptr_void = NULL_type;
287
static TYPE type_wint_t = NULL_type ;
351
static TYPE type_wint_t = NULL_type;
288
 
352
 
289
 
353
 
290
/*
354
/*
291
    FIND A PRINTF ARGUMENT TYPE
355
    FIND A PRINTF ARGUMENT TYPE
292
 
356
 
293
    This routine reads a single printf argument type from the string
357
    This routine reads a single printf argument type from the string
294
    str, adding it to the list p.  It is entered immediately after the
358
    str, adding it to the list p.  It is entered immediately after the
295
    '%' in the format string has been read.
359
    '%' in the format string has been read.
296
*/
360
*/
297
 
361
 
298
static LIST ( TYPE ) add_printf_arg
362
static LIST(TYPE)
299
    PROTO_N ( ( str, p, margs, state ) )
-
 
300
    PROTO_T ( STRING str X LIST ( TYPE ) p X unsigned margs X int *state )
363
add_printf_arg(STRING str, LIST(TYPE) p, unsigned margs, int *state)
301
{
364
{
302
    unsigned flag ;
365
	unsigned flag;
303
    character s [8] ;
366
	character s[8];
304
    string r = s ;
367
	string r = s;
305
    unsigned long c ;
368
	unsigned long c;
306
    TYPE t = NULL_type ;
369
	TYPE t = NULL_type;
307
    int ch = CHAR_SIMPLE ;
370
	int ch = CHAR_SIMPLE;
308
    BUILTIN_TYPE n = ntype_none ;
371
	BUILTIN_TYPE n = ntype_none;
309
    unsigned flags = PRINTF_NONE ;
372
	unsigned flags = PRINTF_NONE;
310
 
-
 
311
    /* Read argument number */
-
 
312
    unsigned arg = read_arg_no ( str, margs ) ;
-
 
313
 
373
 
-
 
374
	/* Read argument number */
-
 
375
	unsigned arg = read_arg_no(str, margs);
-
 
376
 
314
    /* Read flags */
377
	/* Read flags */
315
    do {
378
	do {
316
	c = get_string_char ( str, &ch ) ;
379
		c = get_string_char(str, &ch);
317
	if ( ch == CHAR_SIMPLE ) {
380
		if (ch == CHAR_SIMPLE) {
318
	    if ( c == char_percent && flags == PRINTF_NONE && arg == 0 ) {
381
			if (c == char_percent && flags == PRINTF_NONE &&
-
 
382
			    arg == 0) {
319
		/* Have precisely '%%' */
383
				/* Have precisely '%%' */
320
		return ( p ) ;
384
				return (p);
321
	    }
385
			}
322
	    switch ( c ) {
386
			switch (c) {
-
 
387
			case char_single_quote:
323
		case char_single_quote : flag = PRINTF_THOUSAND ; break ;
388
				flag = PRINTF_THOUSAND;
-
 
389
				break;
-
 
390
			case char_minus:
324
		case char_minus : flag = PRINTF_LEFT ; break ;
391
				flag = PRINTF_LEFT;
-
 
392
				break;
-
 
393
			case char_plus:
325
		case char_plus : flag = PRINTF_SIGN ; break ;
394
				flag = PRINTF_SIGN;
-
 
395
				break;
-
 
396
			case char_space:
326
		case char_space : flag = PRINTF_SPACE ; break ;
397
				flag = PRINTF_SPACE;
-
 
398
				break;
-
 
399
			case char_hash:
327
		case char_hash : flag = PRINTF_ALT ; break ;
400
				flag = PRINTF_ALT;
-
 
401
				break;
-
 
402
			case char_zero:
328
		case char_zero : flag = PRINTF_ZERO ; break ;
403
				flag = PRINTF_ZERO;
-
 
404
				break;
-
 
405
			default:
329
		default : flag = PRINTF_NONE ; break ;
406
				flag = PRINTF_NONE;
-
 
407
				break;
330
	    }
408
			}
331
	    flags |= flag ;
409
			flags |= flag;
332
	} else {
410
		} else {
333
	    flag = PRINTF_NONE ;
411
			flag = PRINTF_NONE;
334
	}
412
		}
335
    } while ( flag != PRINTF_NONE ) ;
413
	} while (flag != PRINTF_NONE);
336
 
414
 
337
    /* Read field width */
415
	/* Read field width */
338
    if ( ch == CHAR_SIMPLE ) {
416
	if (ch == CHAR_SIMPLE) {
339
	if ( c == char_asterix ) {
417
		if (c == char_asterix) {
340
	    unsigned arg2 = read_arg_no ( str, margs ) ;
418
			unsigned arg2 = read_arg_no(str, margs);
341
	    p = set_printf_arg ( p, arg2, type_sint, state ) ;
419
			p = set_printf_arg(p, arg2, type_sint, state);
342
	    c = get_string_char ( str, &ch ) ;
420
			c = get_string_char(str, &ch);
343
	    flags |= PRINTF_WIDTH ;
421
			flags |= PRINTF_WIDTH;
344
	} else if ( c >= char_zero && c <= char_nine ) {
422
		} else if (c >= char_zero && c <= char_nine) {
345
	    unsigned v = 0 ;
423
			unsigned v = 0;
346
	    c = read_width ( str, c, &ch, &v ) ;
424
			c = read_width(str, c, &ch, &v);
347
	    flags |= PRINTF_WIDTH ;
425
			flags |= PRINTF_WIDTH;
-
 
426
		}
-
 
427
	}
-
 
428
 
-
 
429
	/* Read precision */
-
 
430
	if (ch == CHAR_SIMPLE && c == char_dot) {
-
 
431
		c = get_string_char(str, &ch);
-
 
432
		if (ch == CHAR_SIMPLE) {
-
 
433
			if (c == char_asterix) {
-
 
434
				unsigned arg2 = read_arg_no(str, margs);
-
 
435
				p = set_printf_arg(p, arg2, type_sint, state);
-
 
436
				c = get_string_char(str, &ch);
-
 
437
			} else if (c >= char_zero && c <= char_nine) {
-
 
438
				unsigned v = 0;
-
 
439
				c = read_width(str, c, &ch, &v);
-
 
440
			}
-
 
441
		}
-
 
442
		flags |= PRINTF_PREC;
-
 
443
	}
-
 
444
 
-
 
445
	/* Read type modifier */
-
 
446
	*(r++) = char_percent;
-
 
447
	if (ch == CHAR_SIMPLE) {
-
 
448
		switch (c) {
-
 
449
		case char_h:
-
 
450
			n = ntype_sshort;
-
 
451
			break;
-
 
452
		case char_l:
-
 
453
			n = ntype_slong;
-
 
454
			break;
-
 
455
		case char_L:
-
 
456
			n = ntype_ldouble;
-
 
457
			break;
-
 
458
		}
-
 
459
		if (n != ntype_none) {
-
 
460
			*(r++) = (character)c;
-
 
461
			c = get_string_char(str, &ch);
-
 
462
		}
348
	}
463
	}
349
    }
-
 
350
 
464
 
351
    /* Read precision */
465
	/* Read type specifier */
352
    if ( ch == CHAR_SIMPLE && c == char_dot ) {
466
	r[0] = (character)c;
353
	c = get_string_char ( str, &ch ) ;
467
	r[1] = 0;
354
	if ( ch == CHAR_SIMPLE ) {
468
	if (ch == CHAR_SIMPLE) {
355
	    if ( c == char_asterix ) {
469
		switch (c) {
356
		unsigned arg2 = read_arg_no ( str, margs ) ;
470
		case char_c:
357
		p = set_printf_arg ( p, arg2, type_sint, state ) ;
471
			flags &= (PRINTF_ARITH | PRINTF_PREC);
358
		c = get_string_char ( str, &ch ) ;
472
			n = check_format(s, ntype_uchar, n, flags);
359
	    } else if ( c >= char_zero && c <= char_nine ) {
473
			if (n == ntype_none) {
360
		unsigned v = 0 ;
474
				goto wint_lab;
361
		c = read_width ( str, c, &ch, &v ) ;
-
 
362
	    }
475
			}
363
	}
476
			break;
-
 
477
		case char_C:
364
	flags |= PRINTF_PREC ;
478
			flags &= PRINTF_ARITH;
-
 
479
			n = check_format(s, ntype_none, n, flags);
365
    }
480
wint_lab:
366
 
-
 
367
    /* Read type modifier */
481
			t = type_wint_t;
368
    *( r++ ) = char_percent ;
482
			if (IS_NULL_type(t)) {
369
    if ( ch == CHAR_SIMPLE ) {
483
				t = find_std_type("wint_t", 0, 0);
370
	switch ( c ) {
484
				if (!IS_NULL_type(t)) {
371
	    case char_h : n = ntype_sshort ; break ;
485
					type_wint_t = t;
372
	    case char_l : n = ntype_slong ; break ;
486
				} else {
373
	    case char_L : n = ntype_ldouble ; break ;
487
					t = type_error;
-
 
488
				}
374
	}
489
			}
-
 
490
			break;
-
 
491
		case char_d:
375
	if ( n != ntype_none ) {
492
		case char_i:
376
	    *( r++ ) = ( character ) c ;
493
			flags &= PRINTF_ALT;
377
	    c = get_string_char ( str, &ch ) ;
494
			n = check_format(s, ntype_sint, n, flags);
378
	}
495
			break;
379
    }
496
		case char_o:
380
 
-
 
381
    /* Read type specifier */
497
			flags &= (PRINTF_ALT | PRINTF_THOUSAND);
382
    r [0] = ( character ) c ;
498
			n = check_format(s, ntype_uint, n, flags);
-
 
499
			break;
383
    r [1] = 0 ;
500
		case char_u:
384
    if ( ch == CHAR_SIMPLE ) {
501
			flags &= PRINTF_ALT;
-
 
502
			n = check_format(s, ntype_uint, n, flags);
-
 
503
			break;
385
	switch ( c ) {
504
		case char_x:
386
	    case char_c : {
505
		case char_X:
387
		flags &= ( PRINTF_ARITH | PRINTF_PREC ) ;
506
			flags &= PRINTF_THOUSAND;
388
		n = check_format ( s, ntype_uchar, n, flags ) ;
507
			n = check_format(s, ntype_uint, n, flags);
389
		if ( n == ntype_none ) goto wint_lab ;
-
 
390
		break ;
508
			break;
391
	    }
509
		case char_e:
392
	    case char_C : {
510
		case char_E:
393
		flags &= PRINTF_ARITH ;
511
			flags &= PRINTF_THOUSAND;
394
		n = check_format ( s, ntype_none, n, flags ) ;
512
			n = check_format(s, ntype_double, n, flags);
-
 
513
			break;
-
 
514
		case char_f:
-
 
515
		case char_g:
395
		wint_lab : {
516
		case char_G:
-
 
517
			n = check_format(s, ntype_double, n, PRINTF_NONE);
-
 
518
			break;
396
		    t = type_wint_t ;
519
		case char_s:
397
		    if ( IS_NULL_type ( t ) ) {
520
			flags &= PRINTF_ARITH;
398
			t = find_std_type ( "wint_t", 0, 0 ) ;
521
			n = check_format(s, ntype_char, n, flags);
399
			if ( !IS_NULL_type ( t ) ) {
522
			if (n == ntype_char) {
400
			    type_wint_t = t ;
523
				t = ptr_const_char;
401
			} else {
524
			} else {
402
			    t = type_error ;
525
				t = ptr_const_wchar_t;
403
			}
526
			}
404
		    }
527
			n = ntype_none;
405
		}
-
 
406
		break ;
528
			break;
407
	    }
-
 
408
	    case char_d :
529
		case char_S:
409
	    case char_i : {
-
 
410
		flags &= PRINTF_ALT ;
530
			flags &= PRINTF_ARITH;
411
		n = check_format ( s, ntype_sint, n, flags ) ;
531
			n = check_format(s, ntype_none, n, flags);
412
		break ;
-
 
413
	    }
-
 
414
	    case char_o : {
532
			t = ptr_const_wchar_t;
415
		flags &= ( PRINTF_ALT | PRINTF_THOUSAND ) ;
-
 
416
		n = check_format ( s, ntype_uint, n, flags ) ;
-
 
417
		break ;
533
			break;
418
	    }
-
 
419
	    case char_u : {
534
		case char_p:
420
		flags &= PRINTF_ALT ;
535
			flags &= (PRINTF_ARITH | PRINTF_PREC);
421
		n = check_format ( s, ntype_uint, n, flags ) ;
536
			n = check_format(s, ntype_none, n, flags);
422
		break ;
-
 
423
	    }
-
 
424
	    case char_x :
-
 
425
	    case char_X : {
537
			t = type_void_star;
426
		flags &= PRINTF_THOUSAND ;
-
 
427
		n = check_format ( s, ntype_uint, n, flags ) ;
-
 
428
		break ;
538
			break;
429
	    }
-
 
430
	    case char_e :
539
		case char_n:
431
	    case char_E : {
-
 
432
		flags &= PRINTF_THOUSAND ;
-
 
433
		n = check_format ( s, ntype_double, n, flags ) ;
540
			n = check_format(s, ntype_sint, n, flags);
434
		break ;
-
 
435
	    }
-
 
436
	    case char_f :
541
			t = ptr_type_builtin[n];
437
	    case char_g :
542
			n = ntype_none;
438
	    case char_G : {
-
 
439
		n = check_format ( s, ntype_double, n, PRINTF_NONE ) ;
-
 
440
		break ;
543
			break;
441
	    }
544
		default:
442
	    case char_s : {
-
 
443
		flags &= PRINTF_ARITH ;
-
 
444
		n = check_format ( s, ntype_char, n, flags ) ;
545
			report(crt_loc, ERR_printf_unknown(s));
445
		if ( n == ntype_char ) {
546
			t = type_error;
446
		    t = ptr_const_char ;
547
			n = ntype_none;
447
		} else {
548
			break;
448
		    t = ptr_const_wchar_t ;
-
 
449
		}
549
		}
450
		n = ntype_none ;
550
		if (n != ntype_none) {
451
		break ;
-
 
452
	    }
-
 
453
	    case char_S : {
-
 
454
		flags &= PRINTF_ARITH ;
-
 
455
		n = check_format ( s, ntype_none, n, flags ) ;
-
 
456
		t = ptr_const_wchar_t ;
-
 
457
		break ;
-
 
458
	    }
-
 
459
	    case char_p : {
-
 
460
		flags &= ( PRINTF_ARITH | PRINTF_PREC ) ;
-
 
461
		n = check_format ( s, ntype_none, n, flags ) ;
-
 
462
		t = type_void_star ;
551
			t = type_builtin[n];
463
		break ;
-
 
464
	    }
552
		}
465
	    case char_n : {
553
	} else {
466
		n = check_format ( s, ntype_sint, n, flags ) ;
554
		report(crt_loc, ERR_printf_unknown(s));
467
		t = ptr_type_builtin [n] ;
-
 
468
		n = ntype_none ;
555
		t = type_error;
469
		break ;
-
 
470
	    }
556
	}
471
	    default : {
557
	if (!IS_NULL_type(t)) {
472
		report ( crt_loc, ERR_printf_unknown ( s ) ) ;
558
		t = arg_promote_type(t, KILL_err);
473
		t = type_error ;
559
		p = set_printf_arg(p, arg, t, state);
474
		n = ntype_none ;
-
 
475
		break ;
-
 
476
	    }
-
 
477
	}
560
	}
478
	if ( n != ntype_none ) t = type_builtin [n] ;
-
 
479
    } else {
-
 
480
	report ( crt_loc, ERR_printf_unknown ( s ) ) ;
-
 
481
	t = type_error ;
-
 
482
    }
-
 
483
    if ( !IS_NULL_type ( t ) ) {
-
 
484
	t = arg_promote_type ( t, KILL_err ) ;
-
 
485
	p = set_printf_arg ( p, arg, t, state ) ;
-
 
486
    }
-
 
487
    return ( p ) ;
561
	return (p);
488
}
562
}
489
 
563
 
490
 
564
 
491
/*
565
/*
492
    FIND A SCANF ARGUMENT TYPE
566
    FIND A SCANF ARGUMENT TYPE
Line 494... Line 568...
494
    This routine reads a single scanf argument type from the string
568
    This routine reads a single scanf argument type from the string
495
    str, adding it to the list p.  It is entered immediately after the
569
    str, adding it to the list p.  It is entered immediately after the
496
    '%' in the format string has been read.
570
    '%' in the format string has been read.
497
*/
571
*/
498
 
572
 
499
static LIST ( TYPE ) add_scanf_arg
573
static LIST(TYPE)
500
    PROTO_N ( ( str, p, margs, state ) )
-
 
501
    PROTO_T ( STRING str X LIST ( TYPE ) p X unsigned margs X int *state )
574
add_scanf_arg(STRING str, LIST(TYPE) p, unsigned margs, int *state)
502
{
575
{
503
    character s [8] ;
576
	character s[8];
504
    string r = s ;
577
	string r = s;
505
    int ignore = 0 ;
578
	int ignore = 0;
506
    unsigned long c ;
579
	unsigned long c;
507
    TYPE t = NULL_type ;
580
	TYPE t = NULL_type;
508
    int ch = CHAR_SIMPLE ;
581
	int ch = CHAR_SIMPLE;
509
    BUILTIN_TYPE n = ntype_none ;
582
	BUILTIN_TYPE n = ntype_none;
510
    unsigned flags = PRINTF_NONE ;
583
	unsigned flags = PRINTF_NONE;
511
 
584
 
512
    /* Read argument number */
585
	/* Read argument number */
513
    unsigned arg = read_arg_no ( str, margs ) ;
586
	unsigned arg = read_arg_no(str, margs);
514
 
587
 
515
    /* Check for initial '*' */
588
	/* Check for initial '*' */
516
    c = get_string_char ( str, &ch ) ;
589
	c = get_string_char(str, &ch);
517
    if ( ch == CHAR_SIMPLE ) {
590
	if (ch == CHAR_SIMPLE) {
518
	if ( c == char_percent && arg == 0 ) {
591
		if (c == char_percent && arg == 0) {
519
	    /* Have precisely '%%' */
592
			/* Have precisely '%%' */
520
	    return ( p ) ;
593
			return (p);
521
	}
594
		}
522
	if ( c == char_asterix ) {
595
		if (c == char_asterix) {
523
	    c = get_string_char ( str, &ch ) ;
596
			c = get_string_char(str, &ch);
524
	    ignore = 1 ;
597
			ignore = 1;
525
	}
598
		}
526
    }
599
	}
527
 
600
 
528
    /* Read field width */
601
	/* Read field width */
529
    if ( ch == CHAR_SIMPLE && ( c >= char_zero && c <= char_nine ) ) {
602
	if (ch == CHAR_SIMPLE && (c >= char_zero && c <= char_nine)) {
530
	unsigned v = 0 ;
603
		unsigned v = 0;
531
	c = read_width ( str, c, &ch, &v ) ;
604
		c = read_width(str, c, &ch, &v);
532
	flags |= PRINTF_WIDTH ;
605
		flags |= PRINTF_WIDTH;
533
    }
606
	}
534
 
607
 
535
    /* Read type modifier */
608
	/* Read type modifier */
536
    *( r++ ) = char_percent ;
609
	*(r++) = char_percent;
537
    if ( ch == CHAR_SIMPLE ) {
610
	if (ch == CHAR_SIMPLE) {
538
	switch ( c ) {
611
		switch (c) {
-
 
612
		case char_h:
539
	    case char_h : n = ntype_sshort ; break ;
613
			n = ntype_sshort;
-
 
614
			break;
-
 
615
		case char_l:
540
	    case char_l : n = ntype_slong ; break ;
616
			n = ntype_slong;
-
 
617
			break;
-
 
618
		case char_L:
541
	    case char_L : n = ntype_ldouble ; break ;
619
			n = ntype_ldouble;
-
 
620
			break;
542
	}
621
		}
543
	if ( n != ntype_none ) {
622
		if (n != ntype_none) {
544
	    *( r++ ) = ( character ) c ;
623
			*(r++) = (character)c;
545
	    c = get_string_char ( str, &ch ) ;
624
			c = get_string_char(str, &ch);
-
 
625
		}
546
	}
626
	}
547
    }
-
 
548
 
627
 
549
    /* Read type specifier */
628
	/* Read type specifier */
550
    r [0] = ( character ) c ;
629
	r[0] = (character)c;
551
    r [1] = 0 ;
630
	r[1] = 0;
552
    if ( ch == CHAR_SIMPLE ) {
631
	if (ch == CHAR_SIMPLE) {
553
	switch ( c ) {
632
		switch (c) {
554
	    case char_c : {
633
		case char_c:
555
		n = check_format ( s, ntype_char, n, PRINTF_NONE ) ;
634
			n = check_format(s, ntype_char, n, PRINTF_NONE);
556
		break ;
635
			break;
557
	    }
-
 
558
	    case char_C : {
636
		case char_C:
559
		n = check_format ( s, ntype_wchar_t, n, PRINTF_NONE ) ;
637
			n = check_format(s, ntype_wchar_t, n, PRINTF_NONE);
560
		break ;
638
			break;
561
	    }
-
 
562
	    case char_d :
639
		case char_d:
563
	    case char_i : {
640
		case char_i:
564
		n = check_format ( s, ntype_sint, n, PRINTF_NONE ) ;
641
			n = check_format(s, ntype_sint, n, PRINTF_NONE);
565
		break ;
642
			break;
566
	    }
-
 
567
	    case char_o :
643
		case char_o:
568
	    case char_u :
644
		case char_u:
569
	    case char_x :
645
		case char_x:
570
	    case char_X : {
646
		case char_X:
571
		n = check_format ( s, ntype_uint, n, PRINTF_NONE ) ;
647
			n = check_format(s, ntype_uint, n, PRINTF_NONE);
572
		break ;
648
			break;
573
	    }
-
 
574
	    case char_e :
649
		case char_e:
575
	    case char_E :
650
		case char_E:
576
	    case char_f :
651
		case char_f:
577
	    case char_g :
652
		case char_g:
578
	    case char_G : {
653
		case char_G:
579
		n = check_format ( s, ntype_float, n, PRINTF_NONE ) ;
654
			n = check_format(s, ntype_float, n, PRINTF_NONE);
580
		break ;
655
			break;
581
	    }
-
 
582
	    case char_s : {
656
		case char_s:
583
		n = check_format ( s, ntype_char, n, PRINTF_NONE ) ;
657
			n = check_format(s, ntype_char, n, PRINTF_NONE);
584
		break ;
658
			break;
585
	    }
-
 
586
	    case char_open_square : {
659
		case char_open_square:
587
		c = get_string_char ( str, &ch ) ;
660
			c = get_string_char(str, &ch);
588
		if ( ch == CHAR_SIMPLE && c == char_circum ) {
661
			if (ch == CHAR_SIMPLE && c == char_circum) {
589
		    IGNORE get_string_char ( str, &ch ) ;
662
				IGNORE get_string_char(str, &ch);
-
 
663
			}
-
 
664
			do {
-
 
665
				c = get_string_char(str, &ch);
-
 
666
				if (ch == CHAR_NONE) {
-
 
667
					report(crt_loc, ERR_printf_unterm(s));
-
 
668
					break;
-
 
669
				}
-
 
670
			} while (ch != CHAR_SIMPLE || c != char_close_square);
-
 
671
			r = ustrlit("%[...]");
-
 
672
			n = check_format(r, ntype_char, n, PRINTF_NONE);
-
 
673
			break;
-
 
674
		case char_S:
-
 
675
			n = check_format(s, ntype_wchar_t, n, PRINTF_NONE);
-
 
676
			break;
-
 
677
		case char_p:
-
 
678
			n = check_format(s, ntype_none, n, PRINTF_NONE);
-
 
679
			t = ptr_ptr_void;
-
 
680
			break;
-
 
681
		case char_n:
-
 
682
			if (ignore) {
-
 
683
				r = ustrlit("*");
-
 
684
				report(crt_loc, ERR_printf_flags(r, s));
-
 
685
			}
-
 
686
			n = check_format(s, ntype_sint, n, flags);
-
 
687
			break;
-
 
688
		default:
-
 
689
			report(crt_loc, ERR_printf_unknown(s));
-
 
690
			t = type_error;
-
 
691
			n = ntype_none;
-
 
692
			break;
590
		}
693
		}
591
		do {
-
 
592
		    c = get_string_char ( str, &ch ) ;
-
 
593
		    if ( ch == CHAR_NONE ) {
-
 
594
			report ( crt_loc, ERR_printf_unterm ( s ) ) ;
694
		if (n != ntype_none)t = ptr_type_builtin[n];
595
			break ;
-
 
596
		    }
695
	} else {
597
		} while ( ch != CHAR_SIMPLE || c != char_close_square ) ;
-
 
598
		r = ustrlit ( "%[...]" ) ;
-
 
599
		n = check_format ( r, ntype_char, n, PRINTF_NONE ) ;
696
		report(crt_loc, ERR_printf_unknown(s));
600
		break ;
-
 
601
	    }
-
 
602
	    case char_S : {
-
 
603
		n = check_format ( s, ntype_wchar_t, n, PRINTF_NONE ) ;
-
 
604
		break ;
-
 
605
	    }
-
 
606
	    case char_p : {
-
 
607
		n = check_format ( s, ntype_none, n, PRINTF_NONE ) ;
-
 
608
		t = ptr_ptr_void ;
697
		t = type_error;
609
		break ;
-
 
610
	    }
-
 
611
	    case char_n : {
-
 
612
		if ( ignore ) {
-
 
613
		    r = ustrlit ( "*" ) ;
-
 
614
		    report ( crt_loc, ERR_printf_flags ( r, s ) ) ;
-
 
615
		}
698
	}
616
		n = check_format ( s, ntype_sint, n, flags ) ;
699
	if (!IS_NULL_type(t) && !ignore) {
617
		break ;
-
 
618
	    }
-
 
619
	    default : {
-
 
620
		report ( crt_loc, ERR_printf_unknown ( s ) ) ;
700
		p = set_printf_arg(p, arg, t, state);
621
		t = type_error ;
-
 
622
		n = ntype_none ;
-
 
623
		break ;
-
 
624
	    }
-
 
625
	}
701
	}
626
	if ( n != ntype_none ) t = ptr_type_builtin [n] ;
-
 
627
    } else {
-
 
628
	report ( crt_loc, ERR_printf_unknown ( s ) ) ;
-
 
629
	t = type_error ;
-
 
630
    }
-
 
631
    if ( !IS_NULL_type ( t ) && !ignore ) {
-
 
632
	p = set_printf_arg ( p, arg, t, state ) ;
-
 
633
    }
-
 
634
    return ( p ) ;
702
	return (p);
635
}
703
}
636
 
704
 
637
 
705
 
638
/*
706
/*
639
    FIND PRINTF OR SCANF ARGUMENT TYPES
707
    FIND PRINTF OR SCANF ARGUMENT TYPES
Line 642... Line 710...
642
    or scanf-like function with format string fmt.  margs gives the
710
    or scanf-like function with format string fmt.  margs gives the
643
    number argument number which may be specified using '%n$', and pf is
711
    number argument number which may be specified using '%n$', and pf is
644
    the value returned by is_printf_type.
712
    the value returned by is_printf_type.
645
*/
713
*/
646
 
714
 
647
LIST ( TYPE ) find_printf_args
715
LIST(TYPE)
648
    PROTO_N ( ( str, margs, pf ) )
-
 
649
    PROTO_T ( STRING str X unsigned margs X int pf )
716
find_printf_args(STRING str, unsigned margs, int pf)
650
{
717
{
651
    int state = 0 ;
718
	int state = 0;
652
    unsigned long c ;
719
	unsigned long c;
653
    int ch = CHAR_SIMPLE ;
720
	int ch = CHAR_SIMPLE;
654
    LIST ( TYPE ) p = NULL_list ( TYPE ) ;
721
	LIST(TYPE) p = NULL_list(TYPE);
655
    ulong tok = DEREF_ulong ( str_simple_tok ( str ) ) ;
722
	ulong tok = DEREF_ulong(str_simple_tok(str));
656
    COPY_ulong ( str_simple_tok ( str ), 0 ) ;
723
	COPY_ulong(str_simple_tok(str), 0);
657
    while ( c = get_string_char ( str, &ch ), ch != CHAR_NONE ) {
724
	while (c = get_string_char(str, &ch), ch != CHAR_NONE) {
658
	if ( c == char_percent && ch == CHAR_SIMPLE ) {
725
		if (c == char_percent && ch == CHAR_SIMPLE) {
659
	    if ( pf & 1 ) {
726
			if (pf & 1) {
660
		p = add_printf_arg ( str, p, margs, &state ) ;
727
				p = add_printf_arg(str, p, margs, &state);
661
	    } else {
728
			} else {
662
		p = add_scanf_arg ( str, p, margs, &state ) ;
729
				p = add_scanf_arg(str, p, margs, &state);
663
	    }
-
 
664
	}
730
			}
665
    }
-
 
666
    if ( state >= 2 ) {
-
 
667
	int reported = 0 ;
-
 
668
	LIST ( TYPE ) q = p ;
-
 
669
	while ( !IS_NULL_list ( q ) ) {
-
 
670
	    TYPE t = DEREF_type ( HEAD_list ( q ) ) ;
-
 
671
	    if ( IS_NULL_type ( t ) ) {
-
 
672
		/* No format string for given argument */
-
 
673
		if ( !reported ) {
-
 
674
		    unsigned n = LENGTH_list ( q ) ;
-
 
675
		    report ( crt_loc, ERR_printf_arg_none ( n ) ) ;
-
 
676
		    reported = 1 ;
-
 
677
		}
731
		}
678
		COPY_type ( HEAD_list ( q ), type_error ) ;
-
 
679
	    } else {
-
 
680
		reported = 0 ;
-
 
681
	    }
-
 
682
	    q = TAIL_list ( q ) ;
-
 
683
	}
732
	}
-
 
733
	if (state >= 2) {
-
 
734
		int reported = 0;
-
 
735
		LIST(TYPE) q = p;
-
 
736
		while (!IS_NULL_list(q)) {
-
 
737
			TYPE t = DEREF_type(HEAD_list(q));
-
 
738
			if (IS_NULL_type(t)) {
-
 
739
				/* No format string for given argument */
-
 
740
				if (!reported) {
-
 
741
					unsigned n = LENGTH_list(q);
-
 
742
					report(crt_loc, ERR_printf_arg_none(n));
-
 
743
					reported = 1;
684
    }
744
				}
-
 
745
				COPY_type(HEAD_list(q), type_error);
-
 
746
			} else {
-
 
747
				reported = 0;
-
 
748
			}
-
 
749
			q = TAIL_list(q);
-
 
750
		}
-
 
751
	}
685
    COPY_ulong ( str_simple_tok ( str ), tok ) ;
752
	COPY_ulong(str_simple_tok(str), tok);
686
    p = REVERSE_list ( p ) ;
753
	p = REVERSE_list(p);
687
    return ( p ) ;
754
	return (p);
688
}
755
}
689
 
756
 
690
 
757
 
691
/*
758
/*
692
    PRINTF AND SCANF STRING TYPES
759
    PRINTF AND SCANF STRING TYPES
693
 
760
 
694
    Functions like printf and scanf are indicated by an argument with one
761
    Functions like printf and scanf are indicated by an argument with one
695
    of the following types, which equal 'const char *' or 'const wchar_t *'.
762
    of the following types, which equal 'const char *' or 'const wchar_t *'.
696
*/
763
*/
697
 
764
 
698
TYPE type_printf = NULL_type ;
765
TYPE type_printf = NULL_type;
699
TYPE type_scanf = NULL_type ;
766
TYPE type_scanf = NULL_type;
700
TYPE type_wprintf = NULL_type ;
767
TYPE type_wprintf = NULL_type;
701
TYPE type_wscanf = NULL_type ;
768
TYPE type_wscanf = NULL_type;
702
 
769
 
703
 
770
 
704
/*
771
/*
705
    IS A TYPE A PRINTF OR SCANF STRING TYPE?
772
    IS A TYPE A PRINTF OR SCANF STRING TYPE?
706
 
773
 
707
    This routine checks whether the type t is derived from one of the
774
    This routine checks whether the type t is derived from one of the
708
    printf or scanf string types above.  It returns 1 for type_printf,
775
    printf or scanf string types above.  It returns 1 for type_printf,
709
    2 for type_scanf, 3 for type_wprintf and 4 for type_wscanf.
776
    2 for type_scanf, 3 for type_wprintf and 4 for type_wscanf.
710
*/
777
*/
711
 
778
 
712
int is_printf_type
779
int
713
    PROTO_N ( ( t ) )
-
 
714
    PROTO_T ( TYPE t )
780
is_printf_type(TYPE t)
715
{
781
{
716
    IDENTIFIER tid = DEREF_id ( type_name ( t ) ) ;
782
	IDENTIFIER tid = DEREF_id(type_name(t));
717
    if ( !IS_NULL_id ( tid ) ) {
783
	if (!IS_NULL_id(tid)) {
718
	TYPE s = DEREF_type ( id_class_name_etc_defn ( tid ) ) ;
784
		TYPE s = DEREF_type(id_class_name_etc_defn(tid));
719
	if ( IS_type_ptr ( s ) ) {
785
		if (IS_type_ptr(s)) {
720
	    if ( EQ_type ( s, type_printf ) ) return ( 1 ) ;
786
			if (EQ_type(s, type_printf)) {
-
 
787
				return (1);
-
 
788
			}
721
	    if ( EQ_type ( s, type_scanf ) ) return ( 2 ) ;
789
			if (EQ_type(s, type_scanf)) {
-
 
790
				return (2);
-
 
791
			}
722
	    if ( EQ_type ( s, type_wprintf ) ) return ( 3 ) ;
792
			if (EQ_type(s, type_wprintf)) {
-
 
793
				return (3);
-
 
794
			}
723
	    if ( EQ_type ( s, type_wscanf ) ) return ( 4 ) ;
795
			if (EQ_type(s, type_wscanf)) {
-
 
796
				return (4);
-
 
797
			}
-
 
798
		}
724
	}
799
	}
725
    }
-
 
726
    return ( 0 ) ;
800
	return (0);
727
}
801
}
728
 
802
 
729
 
803
 
730
/*
804
/*
731
    INITIALISE PRINTF AND SCANF TYPES
805
    INITIALISE PRINTF AND SCANF TYPES
732
 
806
 
733
    This routine initialises the printf and scanf strings.
807
    This routine initialises the printf and scanf strings.
734
*/
808
*/
735
 
809
 
736
void init_printf
810
void
737
    PROTO_Z ()
811
init_printf(void)
738
{
812
{
739
    TYPE c = qualify_type ( type_char, cv_const, 0 ) ;
813
	TYPE c = qualify_type(type_char, cv_const, 0);
740
    TYPE w = qualify_type ( type_wchar_t, cv_const, 0 ) ;
814
	TYPE w = qualify_type(type_wchar_t, cv_const, 0);
741
    MAKE_type_ptr ( cv_none, c, type_printf ) ;
815
	MAKE_type_ptr(cv_none, c, type_printf);
742
    MAKE_type_ptr ( cv_none, c, type_scanf ) ;
816
	MAKE_type_ptr(cv_none, c, type_scanf);
743
    MAKE_type_ptr ( cv_none, w, type_wprintf ) ;
817
	MAKE_type_ptr(cv_none, w, type_wprintf);
744
    MAKE_type_ptr ( cv_none, w, type_wscanf ) ;
818
	MAKE_type_ptr(cv_none, w, type_wscanf);
745
    MAKE_type_ptr ( cv_none, c, ptr_const_char ) ;
819
	MAKE_type_ptr(cv_none, c, ptr_const_char);
746
    MAKE_type_ptr ( cv_none, w, ptr_const_wchar_t ) ;
820
	MAKE_type_ptr(cv_none, w, ptr_const_wchar_t);
747
    MAKE_type_ptr ( cv_none, type_void_star, ptr_ptr_void ) ;
821
	MAKE_type_ptr(cv_none, type_void_star, ptr_ptr_void);
748
    return ;
822
	return;
749
}
823
}