1281168Spfg/* $NetBSD: emit1.c,v 1.14 2004/06/20 22:20:16 jmc Exp $ */ 212099Sjoerg 312099Sjoerg/* 491586Smarkm * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. 512099Sjoerg * Copyright (c) 1994, 1995 Jochen Pohl 612099Sjoerg * All Rights Reserved. 712099Sjoerg * 812099Sjoerg * Redistribution and use in source and binary forms, with or without 912099Sjoerg * modification, are permitted provided that the following conditions 1012099Sjoerg * are met: 1112099Sjoerg * 1. Redistributions of source code must retain the above copyright 1212099Sjoerg * notice, this list of conditions and the following disclaimer. 1312099Sjoerg * 2. Redistributions in binary form must reproduce the above copyright 1412099Sjoerg * notice, this list of conditions and the following disclaimer in the 1512099Sjoerg * documentation and/or other materials provided with the distribution. 1612099Sjoerg * 3. All advertising materials mentioning features or use of this software 1712099Sjoerg * must display the following acknowledgement: 1812099Sjoerg * This product includes software developed by Jochen Pohl for 1912099Sjoerg * The NetBSD Project. 2012099Sjoerg * 4. The name of the author may not be used to endorse or promote products 2112099Sjoerg * derived from this software without specific prior written permission. 2212099Sjoerg * 2312099Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2412099Sjoerg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2512099Sjoerg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2612099Sjoerg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2712099Sjoerg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2812099Sjoerg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2912099Sjoerg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3012099Sjoerg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3112099Sjoerg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3212099Sjoerg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3312099Sjoerg */ 3412099Sjoerg 3591586Smarkm#include <sys/cdefs.h> 3691586Smarkm#if defined(__RCSID) && !defined(lint) 37281168Spfg__RCSID("$NetBSD: emit1.c,v 1.14 2004/06/20 22:20:16 jmc Exp $"); 3812099Sjoerg#endif 39108470Sschweikh__FBSDID("$FreeBSD$"); 4012099Sjoerg 4112099Sjoerg#include <ctype.h> 4212099Sjoerg 4312099Sjoerg#include "lint1.h" 4412099Sjoerg 4591586Smarkmstatic void outtt(sym_t *, sym_t *); 4691586Smarkmstatic void outfstrg(strg_t *); 4712099Sjoerg 4812099Sjoerg/* 4912099Sjoerg * Write type into the output buffer. 5012099Sjoerg * The type is written as a sequence of substrings, each of which describes a 5112099Sjoerg * node of type type_t 5212099Sjoerg * a node is coded as follows: 5312099Sjoerg * char C 5412099Sjoerg * signed char s C 5512099Sjoerg * unsigned char u C 5612099Sjoerg * short S 5712099Sjoerg * unsigned short u S 5812099Sjoerg * int I 5912099Sjoerg * unsigned int u I 6012099Sjoerg * long L 6112099Sjoerg * unsigned long u L 6212099Sjoerg * long long Q 6312099Sjoerg * unsigned long long u Q 6412099Sjoerg * float s D 6512099Sjoerg * double D 6612099Sjoerg * long double l D 6712099Sjoerg * void V 6812099Sjoerg * * P 6912099Sjoerg * [n] A n 7012099Sjoerg * () F 7112099Sjoerg * (void) F 0 7212099Sjoerg * (n arguments) F n arg1 arg2 ... argn 7312099Sjoerg * (n arguments, ...) F n arg1 arg2 ... argn-1 E 7412099Sjoerg * (a, b, c, ...) f n arg1 arg2 ... 7512099Sjoerg * enum tag e T tag_or_typename 7612099Sjoerg * struct tag s T tag_or_typename 7712099Sjoerg * union tag u T tag_or_typename 7812099Sjoerg * 7912099Sjoerg * tag_or_typename 0 no tag or type name 8012099Sjoerg * 1 n tag Tag 8112099Sjoerg * 2 n typename only type name 8212099Sjoerg * 8312099Sjoerg * spaces are only for better readability 84228992Suqs * additionally it is possible to prepend the characters 'c' (for const) 8512099Sjoerg * and 'v' (for volatile) 8612099Sjoerg */ 8712099Sjoergvoid 8891586Smarkmouttype(type_t *tp) 8912099Sjoerg{ 9012099Sjoerg int t, s, na; 9112099Sjoerg sym_t *arg; 9212099Sjoerg tspec_t ts; 9312099Sjoerg 9412099Sjoerg while (tp != NULL) { 9512099Sjoerg if ((ts = tp->t_tspec) == INT && tp->t_isenum) 9612099Sjoerg ts = ENUM; 9712099Sjoerg switch (ts) { 9812099Sjoerg case CHAR: t = 'C'; s = '\0'; break; 9912099Sjoerg case SCHAR: t = 'C'; s = 's'; break; 10012099Sjoerg case UCHAR: t = 'C'; s = 'u'; break; 10112099Sjoerg case SHORT: t = 'S'; s = '\0'; break; 10212099Sjoerg case USHORT: t = 'S'; s = 'u'; break; 10312099Sjoerg case INT: t = 'I'; s = '\0'; break; 10412099Sjoerg case UINT: t = 'I'; s = 'u'; break; 10512099Sjoerg case LONG: t = 'L'; s = '\0'; break; 10612099Sjoerg case ULONG: t = 'L'; s = 'u'; break; 10712099Sjoerg case QUAD: t = 'Q'; s = '\0'; break; 10812099Sjoerg case UQUAD: t = 'Q'; s = 'u'; break; 10912099Sjoerg case FLOAT: t = 'D'; s = 's'; break; 11012099Sjoerg case DOUBLE: t = 'D'; s = '\0'; break; 11112099Sjoerg case LDOUBLE: t = 'D'; s = 'l'; break; 11212099Sjoerg case VOID: t = 'V'; s = '\0'; break; 11312099Sjoerg case PTR: t = 'P'; s = '\0'; break; 11412099Sjoerg case ARRAY: t = 'A'; s = '\0'; break; 11512099Sjoerg case FUNC: t = 'F'; s = '\0'; break; 11612099Sjoerg case ENUM: t = 'T'; s = 'e'; break; 11712099Sjoerg case STRUCT: t = 'T'; s = 's'; break; 11812099Sjoerg case UNION: t = 'T'; s = 'u'; break; 11912099Sjoerg default: 120281168Spfg LERROR("outtyp()"); 12112099Sjoerg } 12212099Sjoerg if (tp->t_const) 12312099Sjoerg outchar('c'); 12412099Sjoerg if (tp->t_volatile) 12512099Sjoerg outchar('v'); 12612099Sjoerg if (s != '\0') 12712099Sjoerg outchar(s); 12812099Sjoerg outchar(t); 12912099Sjoerg if (ts == ARRAY) { 13012099Sjoerg outint(tp->t_dim); 13112099Sjoerg } else if (ts == ENUM) { 13212099Sjoerg outtt(tp->t_enum->etag, tp->t_enum->etdef); 13312099Sjoerg } else if (ts == STRUCT || ts == UNION) { 13412099Sjoerg outtt(tp->t_str->stag, tp->t_str->stdef); 13512099Sjoerg } else if (ts == FUNC && tp->t_proto) { 13612099Sjoerg na = 0; 13712099Sjoerg for (arg = tp->t_args; arg != NULL; arg = arg->s_nxt) 13812099Sjoerg na++; 13912099Sjoerg if (tp->t_vararg) 14012099Sjoerg na++; 14112099Sjoerg outint(na); 14212099Sjoerg for (arg = tp->t_args; arg != NULL; arg = arg->s_nxt) 14312099Sjoerg outtype(arg->s_type); 14412099Sjoerg if (tp->t_vararg) 14512099Sjoerg outchar('E'); 14612099Sjoerg } 14712099Sjoerg tp = tp->t_subt; 14812099Sjoerg } 14912099Sjoerg} 15012099Sjoerg 15112099Sjoerg/* 15212099Sjoerg * type to string 15312099Sjoerg * used for debugging output 15412099Sjoerg * 15512099Sjoerg * it uses its own output buffer for conversion 15612099Sjoerg */ 15712099Sjoergconst char * 15891586Smarkmttos(type_t *tp) 15912099Sjoerg{ 16012099Sjoerg static ob_t tob; 16112099Sjoerg ob_t tmp; 16212099Sjoerg 16312099Sjoerg if (tob.o_buf == NULL) { 16412099Sjoerg tob.o_len = 64; 16512099Sjoerg tob.o_buf = tob.o_nxt = xmalloc(tob.o_len); 16612099Sjoerg tob.o_end = tob.o_buf + tob.o_len; 16712099Sjoerg } 16812099Sjoerg 16912099Sjoerg tmp = ob; 17012099Sjoerg ob = tob; 17112099Sjoerg ob.o_nxt = ob.o_buf; 17212099Sjoerg outtype(tp); 17312099Sjoerg outchar('\0'); 17412099Sjoerg tob = ob; 17512099Sjoerg ob = tmp; 17612099Sjoerg 17712099Sjoerg return (tob.o_buf); 17812099Sjoerg} 17912099Sjoerg 18012099Sjoerg/* 18112099Sjoerg * write the name of a tag or typename 18212099Sjoerg * 18312099Sjoerg * if the tag is named, the name of the 18412099Sjoerg * tag is written, otherwise, if a typename exists which 18512099Sjoerg * refers to this tag, this typename is written 18612099Sjoerg */ 18712099Sjoergstatic void 18891586Smarkmouttt(sym_t *tag, sym_t *tdef) 18912099Sjoerg{ 19091586Smarkm 19191586Smarkm /* 19291586Smarkm * 0 is no longer used. 19391586Smarkm */ 19412099Sjoerg if (tag->s_name != unnamed) { 19512099Sjoerg outint(1); 19612099Sjoerg outname(tag->s_name); 19712099Sjoerg } else if (tdef != NULL) { 19812099Sjoerg outint(2); 19912099Sjoerg outname(tdef->s_name); 20012099Sjoerg } else { 20191586Smarkm outint(3); 20291586Smarkm outint(tag->s_dpos.p_line); 20391586Smarkm outchar('.'); 20491586Smarkm outint(getfnid(tag->s_dpos.p_file)); 20591586Smarkm outchar('.'); 20691586Smarkm outint(tag->s_dpos.p_uniq); 20712099Sjoerg } 20812099Sjoerg} 20912099Sjoerg 21012099Sjoerg/* 211108470Sschweikh * write information about a global declared/defined symbol 21212099Sjoerg * with storage class extern 21312099Sjoerg * 21412099Sjoerg * informations about function definitions are written in outfdef(), 21512099Sjoerg * not here 21612099Sjoerg */ 21712099Sjoergvoid 21891586Smarkmoutsym(sym_t *sym, scl_t sc, def_t def) 21912099Sjoerg{ 22091586Smarkm 22112099Sjoerg /* 22212099Sjoerg * Static function declarations must also be written to the output 22312099Sjoerg * file. Compatibility of function declarations (for both static 22412099Sjoerg * and extern functions) must be checked in lint2. Lint1 can't do 22512099Sjoerg * this, especially not, if functions are declared at block level 22612099Sjoerg * before their first declaration at level 0. 22712099Sjoerg */ 22812099Sjoerg if (sc != EXTERN && !(sc == STATIC && sym->s_type->t_tspec == FUNC)) 22912099Sjoerg return; 23012099Sjoerg 23112099Sjoerg /* reset buffer */ 23212099Sjoerg outclr(); 23312099Sjoerg 23412099Sjoerg /* 23512099Sjoerg * line number of .c source, 'd' for declaration, Id of current 23612099Sjoerg * source (.c or .h), and line in current source. 23712099Sjoerg */ 23812099Sjoerg outint(csrc_pos.p_line); 23912099Sjoerg outchar('d'); 24012099Sjoerg outint(getfnid(sym->s_dpos.p_file)); 24112099Sjoerg outchar('.'); 24212099Sjoerg outint(sym->s_dpos.p_line); 24312099Sjoerg 24412099Sjoerg /* flags */ 24512099Sjoerg 24612099Sjoerg switch (def) { 24712099Sjoerg case DEF: 24812099Sjoerg /* defined */ 24912099Sjoerg outchar('d'); 25012099Sjoerg break; 25112099Sjoerg case TDEF: 25212099Sjoerg /* tentative defined */ 25312099Sjoerg outchar('t'); 25412099Sjoerg break; 25512099Sjoerg case DECL: 25612099Sjoerg /* declared */ 25712099Sjoerg outchar('e'); 25812099Sjoerg break; 25912099Sjoerg default: 260281168Spfg LERROR("outsym()"); 26112099Sjoerg } 26212099Sjoerg if (llibflg && def != DECL) { 26312099Sjoerg /* 26412099Sjoerg * mark it as used so we get no warnings from lint2 about 26512099Sjoerg * unused symbols in libraries. 26612099Sjoerg */ 26712099Sjoerg outchar('u'); 26812099Sjoerg } 26912099Sjoerg 27012099Sjoerg if (sc == STATIC) 27112099Sjoerg outchar('s'); 27212099Sjoerg 27312099Sjoerg /* name of the symbol */ 27412099Sjoerg outname(sym->s_name); 27512099Sjoerg 27691586Smarkm /* renamed name of symbol, if necessary */ 27791586Smarkm if (sym->s_rename) { 27891586Smarkm outchar('r'); 27991586Smarkm outname(sym->s_rename); 28091586Smarkm } 28191586Smarkm 28212099Sjoerg /* type of the symbol */ 28312099Sjoerg outtype(sym->s_type); 28412099Sjoerg} 28512099Sjoerg 28612099Sjoerg/* 28712099Sjoerg * write information about function definition 28812099Sjoerg * 28912099Sjoerg * this is also done for static functions so we are able to check if 29012099Sjoerg * they are called with proper argument types 29112099Sjoerg */ 29212099Sjoergvoid 29391586Smarkmoutfdef(sym_t *fsym, pos_t *posp, int rval, int osdef, sym_t *args) 29412099Sjoerg{ 29512099Sjoerg int narg; 29612099Sjoerg sym_t *arg; 29712099Sjoerg 29812099Sjoerg /* reset the buffer */ 29912099Sjoerg outclr(); 30012099Sjoerg 30112099Sjoerg /* 30212099Sjoerg * line number of .c source, 'd' for declaration, Id of current 30312099Sjoerg * source (.c or .h), and line in current source 30412099Sjoerg * 30512099Sjoerg * we are already at the end of the function. If we are in the 30612099Sjoerg * .c source, posp->p_line is correct, otherwise csrc_pos.p_line 30712099Sjoerg * (for functions defined in header files). 30812099Sjoerg */ 30912099Sjoerg if (posp->p_file == csrc_pos.p_file) { 31012099Sjoerg outint(posp->p_line); 31112099Sjoerg } else { 31212099Sjoerg outint(csrc_pos.p_line); 31312099Sjoerg } 31412099Sjoerg outchar('d'); 31512099Sjoerg outint(getfnid(posp->p_file)); 31612099Sjoerg outchar('.'); 31712099Sjoerg outint(posp->p_line); 31812099Sjoerg 31912099Sjoerg /* flags */ 32012099Sjoerg 32112099Sjoerg /* both SCANFLIKE and PRINTFLIKE imply VARARGS */ 32212099Sjoerg if (prflstrg != -1) { 32312099Sjoerg nvararg = prflstrg; 32412099Sjoerg } else if (scflstrg != -1) { 32512099Sjoerg nvararg = scflstrg; 32612099Sjoerg } 32712099Sjoerg 32812099Sjoerg if (nvararg != -1) { 32912099Sjoerg outchar('v'); 33012099Sjoerg outint(nvararg); 33112099Sjoerg } 33212099Sjoerg if (scflstrg != -1) { 33312099Sjoerg outchar('S'); 33412099Sjoerg outint(scflstrg); 33512099Sjoerg } 33612099Sjoerg if (prflstrg != -1) { 33712099Sjoerg outchar('P'); 33812099Sjoerg outint(prflstrg); 33912099Sjoerg } 34012099Sjoerg nvararg = prflstrg = scflstrg = -1; 34112099Sjoerg 34212099Sjoerg outchar('d'); 34312099Sjoerg 34412099Sjoerg if (rval) 34512099Sjoerg /* has return value */ 34612099Sjoerg outchar('r'); 34712099Sjoerg 34812099Sjoerg if (llibflg) 34912099Sjoerg /* 35012099Sjoerg * mark it as used so lint2 does not complain about 35112099Sjoerg * unused symbols in libraries 35212099Sjoerg */ 35312099Sjoerg outchar('u'); 35412099Sjoerg 35512099Sjoerg if (osdef) 35612099Sjoerg /* old style function definition */ 35712099Sjoerg outchar('o'); 35812099Sjoerg 35912099Sjoerg if (fsym->s_scl == STATIC) 36012099Sjoerg outchar('s'); 36112099Sjoerg 36212099Sjoerg /* name of function */ 36312099Sjoerg outname(fsym->s_name); 36412099Sjoerg 36591586Smarkm /* renamed name of function, if necessary */ 36691586Smarkm if (fsym->s_rename) { 36791586Smarkm outchar('r'); 36891586Smarkm outname(fsym->s_rename); 36991586Smarkm } 37091586Smarkm 37112099Sjoerg /* argument types and return value */ 37212099Sjoerg if (osdef) { 37312099Sjoerg narg = 0; 37412099Sjoerg for (arg = args; arg != NULL; arg = arg->s_nxt) 37512099Sjoerg narg++; 37612099Sjoerg outchar('f'); 37712099Sjoerg outint(narg); 37812099Sjoerg for (arg = args; arg != NULL; arg = arg->s_nxt) 37912099Sjoerg outtype(arg->s_type); 38012099Sjoerg outtype(fsym->s_type->t_subt); 38112099Sjoerg } else { 38212099Sjoerg outtype(fsym->s_type); 38312099Sjoerg } 38412099Sjoerg} 38512099Sjoerg 38612099Sjoerg/* 38712099Sjoerg * write out all information necessary for lint2 to check function 38812099Sjoerg * calls 38912099Sjoerg * 39012099Sjoerg * rvused is set if the return value is used (asigned to a variable) 39112099Sjoerg * rvdisc is set if the return value is not used and not ignored 39212099Sjoerg * (casted to void) 39312099Sjoerg */ 39412099Sjoergvoid 39591586Smarkmoutcall(tnode_t *tn, int rvused, int rvdisc) 39612099Sjoerg{ 39712099Sjoerg tnode_t *args, *arg; 39812099Sjoerg int narg, n, i; 39991586Smarkm int64_t q; 40012099Sjoerg tspec_t t; 40112099Sjoerg 40212099Sjoerg /* reset buffer */ 40312099Sjoerg outclr(); 40412099Sjoerg 40512099Sjoerg /* 40612099Sjoerg * line number of .c source, 'c' for function call, Id of current 40712099Sjoerg * source (.c or .h), and line in current source 40812099Sjoerg */ 40912099Sjoerg outint(csrc_pos.p_line); 41012099Sjoerg outchar('c'); 41112099Sjoerg outint(getfnid(curr_pos.p_file)); 41212099Sjoerg outchar('.'); 41312099Sjoerg outint(curr_pos.p_line); 41412099Sjoerg 41512099Sjoerg /* 41612099Sjoerg * flags; 'u' and 'i' must be last to make sure a letter 41712099Sjoerg * is between the numeric argument of a flag and the name of 41812099Sjoerg * the function 41912099Sjoerg */ 42012099Sjoerg narg = 0; 42112099Sjoerg args = tn->tn_right; 42212099Sjoerg for (arg = args; arg != NULL; arg = arg->tn_right) 42312099Sjoerg narg++; 42412099Sjoerg /* informations about arguments */ 42512099Sjoerg for (n = 1; n <= narg; n++) { 42612099Sjoerg /* the last argument is the top one in the tree */ 42791586Smarkm for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) 42891586Smarkm continue; 42912099Sjoerg arg = arg->tn_left; 43012099Sjoerg if (arg->tn_op == CON) { 43112099Sjoerg if (isityp(t = arg->tn_type->t_tspec)) { 43212099Sjoerg /* 43312099Sjoerg * XXX it would probably be better to 43412099Sjoerg * explizitly test the sign 43512099Sjoerg */ 43612099Sjoerg if ((q = arg->tn_val->v_quad) == 0) { 43712099Sjoerg /* zero constant */ 43812099Sjoerg outchar('z'); 43912099Sjoerg } else if (msb(q, t, 0) == 0) { 44012099Sjoerg /* positive if casted to signed */ 44112099Sjoerg outchar('p'); 44212099Sjoerg } else { 44312099Sjoerg /* negative if casted to signed */ 44412099Sjoerg outchar('n'); 44512099Sjoerg } 44612099Sjoerg outint(n); 44712099Sjoerg } 44812099Sjoerg } else if (arg->tn_op == AMPER && 44912099Sjoerg arg->tn_left->tn_op == STRING && 45012099Sjoerg arg->tn_left->tn_strg->st_tspec == CHAR) { 45112099Sjoerg /* constant string, write all format specifiers */ 45212099Sjoerg outchar('s'); 45312099Sjoerg outint(n); 45412099Sjoerg outfstrg(arg->tn_left->tn_strg); 45512099Sjoerg } 45612099Sjoerg 45712099Sjoerg } 45812099Sjoerg /* return value discarded/used/ignored */ 45912099Sjoerg outchar(rvdisc ? 'd' : (rvused ? 'u' : 'i')); 46012099Sjoerg 46112099Sjoerg /* name of the called function */ 46212099Sjoerg outname(tn->tn_left->tn_left->tn_sym->s_name); 46312099Sjoerg 46412099Sjoerg /* types of arguments */ 46512099Sjoerg outchar('f'); 46612099Sjoerg outint(narg); 46712099Sjoerg for (n = 1; n <= narg; n++) { 46812099Sjoerg /* the last argument is the top one in the tree */ 46991586Smarkm for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) 47091586Smarkm continue; 47112099Sjoerg outtype(arg->tn_left->tn_type); 47212099Sjoerg } 47312099Sjoerg /* expected type of return value */ 47412099Sjoerg outtype(tn->tn_type); 47512099Sjoerg} 47612099Sjoerg 47712099Sjoerg/* 47812099Sjoerg * extracts potential format specifiers for printf() and scanf() and 47912099Sjoerg * writes them, enclosed in "" and qouted if necessary, to the output buffer 48012099Sjoerg */ 48112099Sjoergstatic void 48291586Smarkmoutfstrg(strg_t *strg) 48312099Sjoerg{ 48412099Sjoerg int c, oc, first; 48512099Sjoerg u_char *cp; 48612099Sjoerg 48712099Sjoerg if (strg->st_tspec != CHAR) 488281168Spfg LERROR("outfstrg()"); 48912099Sjoerg 49012099Sjoerg cp = strg->st_cp; 49112099Sjoerg 49212099Sjoerg outchar('"'); 49312099Sjoerg 49412099Sjoerg c = *cp++; 49512099Sjoerg 49612099Sjoerg while (c != '\0') { 49712099Sjoerg 49812099Sjoerg if (c != '%') { 49912099Sjoerg c = *cp++; 50012099Sjoerg continue; 50112099Sjoerg } 50212099Sjoerg 50312099Sjoerg outqchar('%'); 50412099Sjoerg c = *cp++; 50512099Sjoerg 50612099Sjoerg /* flags for printf and scanf and *-fieldwidth for printf */ 50712099Sjoerg while (c != '\0' && (c == '-' || c == '+' || c == ' ' || 50812099Sjoerg c == '#' || c == '0' || c == '*')) { 50912099Sjoerg outqchar(c); 51012099Sjoerg c = *cp++; 51112099Sjoerg } 51212099Sjoerg 51312099Sjoerg /* numeric field width */ 51412099Sjoerg while (c != '\0' && isdigit(c)) { 51512099Sjoerg outqchar(c); 51612099Sjoerg c = *cp++; 51712099Sjoerg } 51812099Sjoerg 51912099Sjoerg /* precision for printf */ 52012099Sjoerg if (c == '.') { 52112099Sjoerg outqchar(c); 52212099Sjoerg if ((c = *cp++) == '*') { 52312099Sjoerg outqchar(c); 52412099Sjoerg c = *cp++; 52512099Sjoerg } else { 52612099Sjoerg while (c != '\0' && isdigit(c)) { 52712099Sjoerg outqchar(c); 52812099Sjoerg c = *cp++; 52912099Sjoerg } 53012099Sjoerg } 53112099Sjoerg } 53212099Sjoerg 53312099Sjoerg /* h, l, L and q flags fpr printf and scanf */ 53412099Sjoerg if (c == 'h' || c == 'l' || c == 'L' || c == 'q') { 53512099Sjoerg outqchar(c); 53612099Sjoerg c = *cp++; 53712099Sjoerg } 53812099Sjoerg 53912099Sjoerg /* 54012099Sjoerg * The last character. It is always written so we can detect 54112099Sjoerg * invalid format specifiers. 54212099Sjoerg */ 54312099Sjoerg if (c != '\0') { 54412099Sjoerg outqchar(c); 54512099Sjoerg oc = c; 54612099Sjoerg c = *cp++; 54712099Sjoerg /* 54812099Sjoerg * handle [ for scanf. [-] means that a minus sign 54912099Sjoerg * was found at an undefined position. 55012099Sjoerg */ 55112099Sjoerg if (oc == '[') { 55212099Sjoerg if (c == '^') 55312099Sjoerg c = *cp++; 55412099Sjoerg if (c == ']') 55512099Sjoerg c = *cp++; 55612099Sjoerg first = 1; 55712099Sjoerg while (c != '\0' && c != ']') { 55812099Sjoerg if (c == '-') { 55912099Sjoerg if (!first && *cp != ']') 56012099Sjoerg outqchar(c); 56112099Sjoerg } 56212099Sjoerg first = 0; 56312099Sjoerg c = *cp++; 56412099Sjoerg } 56512099Sjoerg if (c == ']') { 56612099Sjoerg outqchar(c); 56712099Sjoerg c = *cp++; 56812099Sjoerg } 56912099Sjoerg } 57012099Sjoerg } 57112099Sjoerg 57212099Sjoerg } 57312099Sjoerg 57412099Sjoerg outchar('"'); 57512099Sjoerg} 57612099Sjoerg 57712099Sjoerg/* 57812099Sjoerg * writes a record if sym was used 57912099Sjoerg */ 58012099Sjoergvoid 58191586Smarkmoutusg(sym_t *sym) 58212099Sjoerg{ 58312099Sjoerg /* reset buffer */ 58412099Sjoerg outclr(); 58512099Sjoerg 58612099Sjoerg /* 58712099Sjoerg * line number of .c source, 'u' for used, Id of current 58812099Sjoerg * source (.c or .h), and line in current source 58912099Sjoerg */ 59012099Sjoerg outint(csrc_pos.p_line); 59112099Sjoerg outchar('u'); 59212099Sjoerg outint(getfnid(curr_pos.p_file)); 59312099Sjoerg outchar('.'); 59412099Sjoerg outint(curr_pos.p_line); 59512099Sjoerg 59612099Sjoerg /* necessary to delimit both numbers */ 59712099Sjoerg outchar('x'); 59812099Sjoerg 59912099Sjoerg /* Den Namen des Symbols ausgeben */ 60012099Sjoerg outname(sym->s_name); 60112099Sjoerg} 602