emit1.c revision 1.2 1 1.2 cgd /* $NetBSD: emit1.c,v 1.2 1995/07/03 21:24:02 cgd Exp $ */
2 1.2 cgd
3 1.1 cgd /*
4 1.1 cgd * Copyright (c) 1994, 1995 Jochen Pohl
5 1.1 cgd * All Rights Reserved.
6 1.1 cgd *
7 1.1 cgd * Redistribution and use in source and binary forms, with or without
8 1.1 cgd * modification, are permitted provided that the following conditions
9 1.1 cgd * are met:
10 1.1 cgd * 1. Redistributions of source code must retain the above copyright
11 1.1 cgd * notice, this list of conditions and the following disclaimer.
12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 cgd * notice, this list of conditions and the following disclaimer in the
14 1.1 cgd * documentation and/or other materials provided with the distribution.
15 1.1 cgd * 3. All advertising materials mentioning features or use of this software
16 1.1 cgd * must display the following acknowledgement:
17 1.1 cgd * This product includes software developed by Jochen Pohl for
18 1.1 cgd * The NetBSD Project.
19 1.1 cgd * 4. The name of the author may not be used to endorse or promote products
20 1.1 cgd * derived from this software without specific prior written permission.
21 1.1 cgd *
22 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 1.1 cgd * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 1.1 cgd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 1.1 cgd * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 1.1 cgd * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 1.1 cgd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 1.1 cgd * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 1.1 cgd * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 1.1 cgd * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 1.1 cgd * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 1.1 cgd */
33 1.1 cgd
34 1.1 cgd #ifndef lint
35 1.2 cgd static char rcsid[] = "$NetBSD: emit1.c,v 1.2 1995/07/03 21:24:02 cgd Exp $";
36 1.1 cgd #endif
37 1.1 cgd
38 1.1 cgd #include <ctype.h>
39 1.1 cgd
40 1.1 cgd #include "lint1.h"
41 1.1 cgd
42 1.1 cgd static void outtt __P((sym_t *, sym_t *));
43 1.1 cgd static void outfstrg __P((strg_t *));
44 1.1 cgd
45 1.1 cgd /*
46 1.1 cgd * Write type into the output buffer.
47 1.1 cgd * The type is written as a sequence of substrings, each of which describes a
48 1.1 cgd * node of type type_t
49 1.1 cgd * a node is coded as follows:
50 1.1 cgd * char C
51 1.1 cgd * signed char s C
52 1.1 cgd * unsigned char u C
53 1.1 cgd * short S
54 1.1 cgd * unsigned short u S
55 1.1 cgd * int I
56 1.1 cgd * unsigned int u I
57 1.1 cgd * long L
58 1.1 cgd * unsigned long u L
59 1.1 cgd * long long Q
60 1.1 cgd * unsigned long long u Q
61 1.1 cgd * float s D
62 1.1 cgd * double D
63 1.1 cgd * long double l D
64 1.1 cgd * void V
65 1.1 cgd * * P
66 1.1 cgd * [n] A n
67 1.1 cgd * () F
68 1.1 cgd * (void) F 0
69 1.1 cgd * (n arguments) F n arg1 arg2 ... argn
70 1.1 cgd * (n arguments, ...) F n arg1 arg2 ... argn-1 E
71 1.1 cgd * (a, b, c, ...) f n arg1 arg2 ...
72 1.1 cgd * enum tag e T tag_or_typename
73 1.1 cgd * struct tag s T tag_or_typename
74 1.1 cgd * union tag u T tag_or_typename
75 1.1 cgd *
76 1.1 cgd * tag_or_typename 0 no tag or type name
77 1.1 cgd * 1 n tag Tag
78 1.1 cgd * 2 n typename only type name
79 1.1 cgd *
80 1.1 cgd * spaces are only for better readability
81 1.1 cgd * additionaly it is possible to prepend the characters 'c' (for const)
82 1.1 cgd * and 'v' (for volatile)
83 1.1 cgd */
84 1.1 cgd void
85 1.1 cgd outtype(tp)
86 1.1 cgd type_t *tp;
87 1.1 cgd {
88 1.1 cgd int t, s, na;
89 1.1 cgd sym_t *arg;
90 1.1 cgd tspec_t ts;
91 1.1 cgd
92 1.1 cgd while (tp != NULL) {
93 1.1 cgd if ((ts = tp->t_tspec) == INT && tp->t_isenum)
94 1.1 cgd ts = ENUM;
95 1.1 cgd switch (ts) {
96 1.1 cgd case CHAR: t = 'C'; s = '\0'; break;
97 1.1 cgd case SCHAR: t = 'C'; s = 's'; break;
98 1.1 cgd case UCHAR: t = 'C'; s = 'u'; break;
99 1.1 cgd case SHORT: t = 'S'; s = '\0'; break;
100 1.1 cgd case USHORT: t = 'S'; s = 'u'; break;
101 1.1 cgd case INT: t = 'I'; s = '\0'; break;
102 1.1 cgd case UINT: t = 'I'; s = 'u'; break;
103 1.1 cgd case LONG: t = 'L'; s = '\0'; break;
104 1.1 cgd case ULONG: t = 'L'; s = 'u'; break;
105 1.1 cgd case QUAD: t = 'Q'; s = '\0'; break;
106 1.1 cgd case UQUAD: t = 'Q'; s = 'u'; break;
107 1.1 cgd case FLOAT: t = 'D'; s = 's'; break;
108 1.1 cgd case DOUBLE: t = 'D'; s = '\0'; break;
109 1.1 cgd case LDOUBLE: t = 'D'; s = 'l'; break;
110 1.1 cgd case VOID: t = 'V'; s = '\0'; break;
111 1.1 cgd case PTR: t = 'P'; s = '\0'; break;
112 1.1 cgd case ARRAY: t = 'A'; s = '\0'; break;
113 1.1 cgd case FUNC: t = 'F'; s = '\0'; break;
114 1.1 cgd case ENUM: t = 'T'; s = 'e'; break;
115 1.1 cgd case STRUCT: t = 'T'; s = 's'; break;
116 1.1 cgd case UNION: t = 'T'; s = 'u'; break;
117 1.1 cgd default:
118 1.1 cgd lerror("outtyp() 1");
119 1.1 cgd }
120 1.1 cgd if (tp->t_const)
121 1.1 cgd outchar('c');
122 1.1 cgd if (tp->t_volatile)
123 1.1 cgd outchar('v');
124 1.1 cgd if (s != '\0')
125 1.1 cgd outchar(s);
126 1.1 cgd outchar(t);
127 1.1 cgd if (ts == ARRAY) {
128 1.1 cgd outint(tp->t_dim);
129 1.1 cgd } else if (ts == ENUM) {
130 1.1 cgd outtt(tp->t_enum->etag, tp->t_enum->etdef);
131 1.1 cgd } else if (ts == STRUCT || ts == UNION) {
132 1.1 cgd outtt(tp->t_str->stag, tp->t_str->stdef);
133 1.1 cgd } else if (ts == FUNC && tp->t_proto) {
134 1.1 cgd na = 0;
135 1.1 cgd for (arg = tp->t_args; arg != NULL; arg = arg->s_nxt)
136 1.1 cgd na++;
137 1.1 cgd if (tp->t_vararg)
138 1.1 cgd na++;
139 1.1 cgd outint(na);
140 1.1 cgd for (arg = tp->t_args; arg != NULL; arg = arg->s_nxt)
141 1.1 cgd outtype(arg->s_type);
142 1.1 cgd if (tp->t_vararg)
143 1.1 cgd outchar('E');
144 1.1 cgd }
145 1.1 cgd tp = tp->t_subt;
146 1.1 cgd }
147 1.1 cgd }
148 1.1 cgd
149 1.1 cgd /*
150 1.1 cgd * type to string
151 1.1 cgd * used for debugging output
152 1.1 cgd *
153 1.1 cgd * it uses its own output buffer for conversion
154 1.1 cgd */
155 1.1 cgd const char *
156 1.1 cgd ttos(tp)
157 1.1 cgd type_t *tp;
158 1.1 cgd {
159 1.1 cgd static ob_t tob;
160 1.1 cgd ob_t tmp;
161 1.1 cgd
162 1.1 cgd if (tob.o_buf == NULL) {
163 1.1 cgd tob.o_len = 64;
164 1.1 cgd tob.o_buf = tob.o_nxt = xmalloc(tob.o_len);
165 1.1 cgd tob.o_end = tob.o_buf + tob.o_len;
166 1.1 cgd }
167 1.1 cgd
168 1.1 cgd tmp = ob;
169 1.1 cgd ob = tob;
170 1.1 cgd ob.o_nxt = ob.o_buf;
171 1.1 cgd outtype(tp);
172 1.1 cgd outchar('\0');
173 1.1 cgd tob = ob;
174 1.1 cgd ob = tmp;
175 1.1 cgd
176 1.1 cgd return (tob.o_buf);
177 1.1 cgd }
178 1.1 cgd
179 1.1 cgd /*
180 1.1 cgd * write the name of a tag or typename
181 1.1 cgd *
182 1.1 cgd * if the tag is named, the name of the
183 1.1 cgd * tag is written, otherwise, if a typename exists which
184 1.1 cgd * refers to this tag, this typename is written
185 1.1 cgd */
186 1.1 cgd static void
187 1.1 cgd outtt(tag, tdef)
188 1.1 cgd sym_t *tag, *tdef;
189 1.1 cgd {
190 1.1 cgd if (tag->s_name != unnamed) {
191 1.1 cgd outint(1);
192 1.1 cgd outname(tag->s_name);
193 1.1 cgd } else if (tdef != NULL) {
194 1.1 cgd outint(2);
195 1.1 cgd outname(tdef->s_name);
196 1.1 cgd } else {
197 1.1 cgd outint(0);
198 1.1 cgd }
199 1.1 cgd }
200 1.1 cgd
201 1.1 cgd /*
202 1.1 cgd * write information about an global with storage class extern
203 1.1 cgd * declared/defined symbol
204 1.1 cgd *
205 1.1 cgd * informations about function definitions are written in outfdef(),
206 1.1 cgd * not here
207 1.1 cgd */
208 1.1 cgd void
209 1.1 cgd outsym(sym, sc)
210 1.1 cgd sym_t *sym;
211 1.1 cgd scl_t sc;
212 1.1 cgd {
213 1.1 cgd /*
214 1.1 cgd * Static function declarations must also be written to the output
215 1.1 cgd * file. Compatibility of function declarations (for both static
216 1.1 cgd * and extern functions) must be checked in lint2. Lint1 can't do
217 1.1 cgd * this, especially not, if functions are declared at block level
218 1.1 cgd * before their first declaration at level 0.
219 1.1 cgd */
220 1.1 cgd if (sc != EXTERN && !(sc == STATIC && sym->s_type->t_tspec == FUNC))
221 1.1 cgd return;
222 1.1 cgd
223 1.1 cgd /* reset buffer */
224 1.1 cgd outclr();
225 1.1 cgd
226 1.1 cgd /*
227 1.1 cgd * line number of .c source, 'd' for declaration, Id of current
228 1.1 cgd * source (.c or .h), and line in current source.
229 1.1 cgd */
230 1.1 cgd outint(csrc_pos.p_line);
231 1.1 cgd outchar('d');
232 1.1 cgd outint(getfnid(sym->s_dpos.p_file));
233 1.1 cgd outchar('.');
234 1.1 cgd outint(sym->s_dpos.p_line);
235 1.1 cgd
236 1.1 cgd /* flags */
237 1.1 cgd
238 1.1 cgd switch (sym->s_def) {
239 1.1 cgd case DEF:
240 1.1 cgd /* defined */
241 1.1 cgd outchar('d');
242 1.1 cgd break;
243 1.1 cgd case TDEF:
244 1.1 cgd /* tentative defined */
245 1.1 cgd outchar('t');
246 1.1 cgd break;
247 1.1 cgd case DECL:
248 1.1 cgd /* declared */
249 1.1 cgd outchar('e');
250 1.1 cgd break;
251 1.1 cgd default:
252 1.1 cgd lerror("outsym() 2");
253 1.1 cgd }
254 1.1 cgd if (llibflg && sym->s_def != DECL) {
255 1.1 cgd /*
256 1.1 cgd * mark it as used so we get no warnings from lint2 about
257 1.1 cgd * unused symbols in libraries.
258 1.1 cgd */
259 1.1 cgd outchar('u');
260 1.1 cgd }
261 1.1 cgd
262 1.1 cgd if (sc == STATIC)
263 1.1 cgd outchar('s');
264 1.1 cgd
265 1.1 cgd /* name of the symbol */
266 1.1 cgd outname(sym->s_name);
267 1.1 cgd
268 1.1 cgd /* type of the symbol */
269 1.1 cgd outtype(sym->s_type);
270 1.1 cgd }
271 1.1 cgd
272 1.1 cgd /*
273 1.1 cgd * write information about function definition
274 1.1 cgd *
275 1.1 cgd * this is also done for static functions so we are able to check if
276 1.1 cgd * they are called with proper argument types
277 1.1 cgd */
278 1.1 cgd void
279 1.1 cgd outfdef(fsym, tp, posp, rval, osdef, args)
280 1.1 cgd sym_t *fsym, *args;
281 1.1 cgd type_t *tp;
282 1.1 cgd pos_t *posp;
283 1.1 cgd int rval, osdef;
284 1.1 cgd {
285 1.1 cgd int narg;
286 1.1 cgd sym_t *arg;
287 1.1 cgd
288 1.1 cgd /* reset the buffer */
289 1.1 cgd outclr();
290 1.1 cgd
291 1.1 cgd /*
292 1.1 cgd * line number of .c source, 'd' for declaration, Id of current
293 1.1 cgd * source (.c or .h), and line in current source
294 1.1 cgd *
295 1.1 cgd * we are already at the end of the function. If we are in the
296 1.1 cgd * .c source, posp->p_line is correct, otherwise csrc_pos.p_line
297 1.1 cgd * (for functions defined in header files).
298 1.1 cgd */
299 1.1 cgd if (posp->p_file == csrc_pos.p_file) {
300 1.1 cgd outint(posp->p_line);
301 1.1 cgd } else {
302 1.1 cgd outint(csrc_pos.p_line);
303 1.1 cgd }
304 1.1 cgd outchar('d');
305 1.1 cgd outint(getfnid(posp->p_file));
306 1.1 cgd outchar('.');
307 1.1 cgd outint(posp->p_line);
308 1.1 cgd
309 1.1 cgd /* flags */
310 1.1 cgd
311 1.1 cgd /* both SCANFLIKE and PRINTFLIKE imply VARARGS */
312 1.1 cgd if (prflstrg != -1) {
313 1.1 cgd nvararg = prflstrg;
314 1.1 cgd } else if (scflstrg != -1) {
315 1.1 cgd nvararg = scflstrg;
316 1.1 cgd }
317 1.1 cgd
318 1.1 cgd if (nvararg != -1) {
319 1.1 cgd outchar('v');
320 1.1 cgd outint(nvararg);
321 1.1 cgd }
322 1.1 cgd if (scflstrg != -1) {
323 1.1 cgd outchar('S');
324 1.1 cgd outint(scflstrg);
325 1.1 cgd }
326 1.1 cgd if (prflstrg != -1) {
327 1.1 cgd outchar('P');
328 1.1 cgd outint(prflstrg);
329 1.1 cgd }
330 1.1 cgd nvararg = prflstrg = scflstrg = -1;
331 1.1 cgd
332 1.1 cgd outchar('d');
333 1.1 cgd
334 1.1 cgd if (rval)
335 1.1 cgd /* has return value */
336 1.1 cgd outchar('r');
337 1.1 cgd
338 1.1 cgd if (llibflg)
339 1.1 cgd /*
340 1.1 cgd * mark it as used so lint2 does not complain about
341 1.1 cgd * unused symbols in libraries
342 1.1 cgd */
343 1.1 cgd outchar('u');
344 1.1 cgd
345 1.1 cgd if (osdef)
346 1.1 cgd /* old style function definition */
347 1.1 cgd outchar('o');
348 1.1 cgd
349 1.1 cgd if (fsym->s_scl == STATIC)
350 1.1 cgd outchar('s');
351 1.1 cgd
352 1.1 cgd /* name of function */
353 1.1 cgd outname(fsym->s_name);
354 1.1 cgd
355 1.1 cgd /* argument types and return value */
356 1.1 cgd if (osdef) {
357 1.1 cgd narg = 0;
358 1.1 cgd for (arg = args; arg != NULL; arg = arg->s_nxt)
359 1.1 cgd narg++;
360 1.1 cgd outchar('f');
361 1.1 cgd outint(narg);
362 1.1 cgd for (arg = args; arg != NULL; arg = arg->s_nxt)
363 1.1 cgd outtype(arg->s_type);
364 1.1 cgd outtype(tp->t_subt);
365 1.1 cgd } else {
366 1.1 cgd outtype(tp);
367 1.1 cgd }
368 1.1 cgd }
369 1.1 cgd
370 1.1 cgd /*
371 1.1 cgd * write out all information necessary for lint2 to check function
372 1.1 cgd * calls
373 1.1 cgd *
374 1.1 cgd * rvused is set if the return value is used (asigned to a variable)
375 1.1 cgd * rvdisc is set if the return value is not used and not ignored
376 1.1 cgd * (casted to void)
377 1.1 cgd */
378 1.1 cgd void
379 1.1 cgd outcall(tn, rvused, rvdisc)
380 1.1 cgd tnode_t *tn;
381 1.1 cgd int rvused, rvdisc;
382 1.1 cgd {
383 1.1 cgd tnode_t *args, *arg;
384 1.1 cgd int narg, n, i;
385 1.1 cgd quad_t q;
386 1.1 cgd tspec_t t;
387 1.1 cgd
388 1.1 cgd /* reset buffer */
389 1.1 cgd outclr();
390 1.1 cgd
391 1.1 cgd /*
392 1.1 cgd * line number of .c source, 'c' for function call, Id of current
393 1.1 cgd * source (.c or .h), and line in current source
394 1.1 cgd */
395 1.1 cgd outint(csrc_pos.p_line);
396 1.1 cgd outchar('c');
397 1.1 cgd outint(getfnid(curr_pos.p_file));
398 1.1 cgd outchar('.');
399 1.1 cgd outint(curr_pos.p_line);
400 1.1 cgd
401 1.1 cgd /*
402 1.1 cgd * flags; 'u' and 'i' must be last to make sure a letter
403 1.1 cgd * is between the numeric argument of a flag and the name of
404 1.1 cgd * the function
405 1.1 cgd */
406 1.1 cgd narg = 0;
407 1.1 cgd args = tn->tn_right;
408 1.1 cgd for (arg = args; arg != NULL; arg = arg->tn_right)
409 1.1 cgd narg++;
410 1.1 cgd /* informations about arguments */
411 1.1 cgd for (n = 1; n <= narg; n++) {
412 1.1 cgd /* the last argument is the top one in the tree */
413 1.1 cgd for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) ;
414 1.1 cgd arg = arg->tn_left;
415 1.1 cgd if (arg->tn_op == CON) {
416 1.1 cgd if (isityp(t = arg->tn_type->t_tspec)) {
417 1.1 cgd /*
418 1.1 cgd * XXX it would probably be better to
419 1.1 cgd * explizitly test the sign
420 1.1 cgd */
421 1.1 cgd if ((q = arg->tn_val->v_quad) == 0) {
422 1.1 cgd /* zero constant */
423 1.1 cgd outchar('z');
424 1.1 cgd } else if (msb(q, t, 0) == 0) {
425 1.1 cgd /* positive if casted to signed */
426 1.1 cgd outchar('p');
427 1.1 cgd } else {
428 1.1 cgd /* negative if casted to signed */
429 1.1 cgd outchar('n');
430 1.1 cgd }
431 1.1 cgd outint(n);
432 1.1 cgd }
433 1.1 cgd } else if (arg->tn_op == AMPER &&
434 1.1 cgd arg->tn_left->tn_op == STRING &&
435 1.1 cgd arg->tn_left->tn_strg->st_tspec == CHAR) {
436 1.1 cgd /* constant string, write all format specifiers */
437 1.1 cgd outchar('s');
438 1.1 cgd outint(n);
439 1.1 cgd outfstrg(arg->tn_left->tn_strg);
440 1.1 cgd }
441 1.1 cgd
442 1.1 cgd }
443 1.1 cgd /* return value discarded/used/ignored */
444 1.1 cgd outchar(rvdisc ? 'd' : (rvused ? 'u' : 'i'));
445 1.1 cgd
446 1.1 cgd /* name of the called function */
447 1.1 cgd outname(tn->tn_left->tn_left->tn_sym->s_name);
448 1.1 cgd
449 1.1 cgd /* types of arguments */
450 1.1 cgd outchar('f');
451 1.1 cgd outint(narg);
452 1.1 cgd for (n = 1; n <= narg; n++) {
453 1.1 cgd /* the last argument is the top one in the tree */
454 1.1 cgd for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) ;
455 1.1 cgd outtype(arg->tn_left->tn_type);
456 1.1 cgd }
457 1.1 cgd /* expected type of return value */
458 1.1 cgd outtype(tn->tn_type);
459 1.1 cgd }
460 1.1 cgd
461 1.1 cgd /*
462 1.1 cgd * extracts potential format specifiers for printf() and scanf() and
463 1.1 cgd * writes them, enclosed in "" and qouted if necessary, to the output buffer
464 1.1 cgd */
465 1.1 cgd static void
466 1.1 cgd outfstrg(strg)
467 1.1 cgd strg_t *strg;
468 1.1 cgd {
469 1.1 cgd int c, oc, first;
470 1.1 cgd u_char *cp;
471 1.1 cgd
472 1.1 cgd if (strg->st_tspec != CHAR)
473 1.1 cgd lerror("outfstrg() 1");
474 1.1 cgd
475 1.1 cgd cp = strg->st_cp;
476 1.1 cgd
477 1.1 cgd outchar('"');
478 1.1 cgd
479 1.1 cgd c = *cp++;
480 1.1 cgd
481 1.1 cgd while (c != '\0') {
482 1.1 cgd
483 1.1 cgd if (c != '%') {
484 1.1 cgd c = *cp++;
485 1.1 cgd continue;
486 1.1 cgd }
487 1.1 cgd
488 1.1 cgd outqchar('%');
489 1.1 cgd c = *cp++;
490 1.1 cgd
491 1.1 cgd /* flags for printf and scanf and *-fieldwidth for printf */
492 1.1 cgd while (c != '\0' && (c == '-' || c == '+' || c == ' ' ||
493 1.1 cgd c == '#' || c == '0' || c == '*')) {
494 1.1 cgd outqchar(c);
495 1.1 cgd c = *cp++;
496 1.1 cgd }
497 1.1 cgd
498 1.1 cgd /* numeric field width */
499 1.1 cgd while (c != '\0' && isdigit(c)) {
500 1.1 cgd outqchar(c);
501 1.1 cgd c = *cp++;
502 1.1 cgd }
503 1.1 cgd
504 1.1 cgd /* precision for printf */
505 1.1 cgd if (c == '.') {
506 1.1 cgd outqchar(c);
507 1.1 cgd if ((c = *cp++) == '*') {
508 1.1 cgd outqchar(c);
509 1.1 cgd c = *cp++;
510 1.1 cgd } else {
511 1.1 cgd while (c != '\0' && isdigit(c)) {
512 1.1 cgd outqchar(c);
513 1.1 cgd c = *cp++;
514 1.1 cgd }
515 1.1 cgd }
516 1.1 cgd }
517 1.1 cgd
518 1.1 cgd /* h, l, L and q flags fpr printf and scanf */
519 1.1 cgd if (c == 'h' || c == 'l' || c == 'L' || c == 'q') {
520 1.1 cgd outqchar(c);
521 1.1 cgd c = *cp++;
522 1.1 cgd }
523 1.1 cgd
524 1.1 cgd /*
525 1.1 cgd * The last character. It is always written so we can detect
526 1.1 cgd * invalid format specifiers.
527 1.1 cgd */
528 1.1 cgd if (c != '\0') {
529 1.1 cgd outqchar(c);
530 1.1 cgd oc = c;
531 1.1 cgd c = *cp++;
532 1.1 cgd /*
533 1.1 cgd * handle [ for scanf. [-] means that a minus sign
534 1.1 cgd * was found at an undefined position.
535 1.1 cgd */
536 1.1 cgd if (oc == '[') {
537 1.1 cgd if (c == '^')
538 1.1 cgd c = *cp++;
539 1.1 cgd if (c == ']')
540 1.1 cgd c = *cp++;
541 1.1 cgd first = 1;
542 1.1 cgd while (c != '\0' && c != ']') {
543 1.1 cgd if (c == '-') {
544 1.1 cgd if (!first && *cp != ']')
545 1.1 cgd outqchar(c);
546 1.1 cgd }
547 1.1 cgd first = 0;
548 1.1 cgd c = *cp++;
549 1.1 cgd }
550 1.1 cgd if (c == ']') {
551 1.1 cgd outqchar(c);
552 1.1 cgd c = *cp++;
553 1.1 cgd }
554 1.1 cgd }
555 1.1 cgd }
556 1.1 cgd
557 1.1 cgd }
558 1.1 cgd
559 1.1 cgd outchar('"');
560 1.1 cgd }
561 1.1 cgd
562 1.1 cgd /*
563 1.1 cgd * writes a record if sym was used
564 1.1 cgd */
565 1.1 cgd void
566 1.1 cgd outusg(sym)
567 1.1 cgd sym_t *sym;
568 1.1 cgd {
569 1.1 cgd /* reset buffer */
570 1.1 cgd outclr();
571 1.1 cgd
572 1.1 cgd /*
573 1.1 cgd * line number of .c source, 'u' for used, Id of current
574 1.1 cgd * source (.c or .h), and line in current source
575 1.1 cgd */
576 1.1 cgd outint(csrc_pos.p_line);
577 1.1 cgd outchar('u');
578 1.1 cgd outint(getfnid(curr_pos.p_file));
579 1.1 cgd outchar('.');
580 1.1 cgd outint(curr_pos.p_line);
581 1.1 cgd
582 1.1 cgd /* necessary to delimit both numbers */
583 1.1 cgd outchar('x');
584 1.1 cgd
585 1.1 cgd /* Den Namen des Symbols ausgeben */
586 1.1 cgd outname(sym->s_name);
587 1.1 cgd }
588