summaryrefslogtreecommitdiff
path: root/usr.bin/xlint/lint1/emit1.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/xlint/lint1/emit1.c')
-rw-r--r--usr.bin/xlint/lint1/emit1.c589
1 files changed, 0 insertions, 589 deletions
diff --git a/usr.bin/xlint/lint1/emit1.c b/usr.bin/xlint/lint1/emit1.c
deleted file mode 100644
index 28f962cd549..00000000000
--- a/usr.bin/xlint/lint1/emit1.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/* $OpenBSD: emit1.c,v 1.9 2011/09/21 18:08:07 jsg Exp $ */
-/* $NetBSD: emit1.c,v 1.4 1995/10/02 17:21:28 jpo Exp $ */
-
-/*
- * Copyright (c) 1994, 1995 Jochen Pohl
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Jochen Pohl for
- * The NetBSD Project.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <ctype.h>
-
-#include "lint1.h"
-
-static void outtt(sym_t *, sym_t *);
-static void outfstrg(strg_t *);
-
-/*
- * Write type into the output buffer.
- * The type is written as a sequence of substrings, each of which describes a
- * node of type type_t
- * a node is coded as follows:
- * _Bool B
- * char C
- * signed char s C
- * unsigned char u C
- * short S
- * unsigned short u S
- * int I
- * unsigned int u I
- * long L
- * unsigned long u L
- * long long Q
- * unsigned long long u Q
- * float s D
- * double D
- * long double l D
- * float _Complex s X
- * double _Complex X
- * long double _Complex l X
- * float _Imaginary s J
- * double _Imaginary J
- * long double _Imaginary l J
- * void V
- * * P
- * [n] A n
- * () F
- * (void) F 0
- * (n arguments) F n arg1 arg2 ... argn
- * (n arguments, ...) F n arg1 arg2 ... argn-1 E
- * (a, b, c, ...) f n arg1 arg2 ...
- * enum tag e T tag_or_typename
- * struct tag s T tag_or_typename
- * union tag u T tag_or_typename
- *
- * tag_or_typename 0 no tag or type name
- * 1 n tag Tag
- * 2 n typename only type name
- *
- * spaces are only for better readability
- * additionaly it is possible to prepend the characters 'c' (for const)
- * and 'v' (for volatile)
- */
-void
-outtype(type_t *tp)
-{
- int t, s, na;
- sym_t *arg;
- tspec_t ts;
-
- while (tp != NULL) {
- if ((ts = tp->t_tspec) == INT && tp->t_isenum)
- ts = ENUM;
- switch (ts) {
- case BOOL: t = 'B'; s = '\0'; break;
- case CHAR: t = 'C'; s = '\0'; break;
- case SCHAR: t = 'C'; s = 's'; break;
- case UCHAR: t = 'C'; s = 'u'; break;
- case SHORT: t = 'S'; s = '\0'; break;
- case USHORT: t = 'S'; s = 'u'; break;
- case INT: t = 'I'; s = '\0'; break;
- case UINT: t = 'I'; s = 'u'; break;
- case LONG: t = 'L'; s = '\0'; break;
- case ULONG: t = 'L'; s = 'u'; break;
- case QUAD: t = 'Q'; s = '\0'; break;
- case UQUAD: t = 'Q'; s = 'u'; break;
- case FLOAT: t = 'D'; s = 's'; break;
- case DOUBLE: t = 'D'; s = '\0'; break;
- case LDOUBLE: t = 'D'; s = 'l'; break;
- case COMPLEX: t = 'X'; s = 's'; break;
- case DCOMPLEX: t = 'X'; s = '\0'; break;
- case LDCOMPLEX: t = 'X'; s = 'l'; break;
- case IMAGINARY: t = 'J'; s = 's'; break;
- case DIMAGINARY: t = 'J'; s = '\0'; break;
- case LDIMAGINARY:t = 'J'; s = 'l'; break;
- case VOID: t = 'V'; s = '\0'; break;
- case PTR: t = 'P'; s = '\0'; break;
- case ARRAY: t = 'A'; s = '\0'; break;
- case FUNC: t = 'F'; s = '\0'; break;
- case ENUM: t = 'T'; s = 'e'; break;
- case STRUCT: t = 'T'; s = 's'; break;
- case UNION: t = 'T'; s = 'u'; break;
- default:
- lerror("outtyp() 1");
- }
- if (tp->t_const)
- outchar('c');
- if (tp->t_volatile)
- outchar('v');
- if (s != '\0')
- outchar(s);
- outchar(t);
- if (ts == ARRAY) {
- outint(tp->t_dim);
- } else if (ts == ENUM) {
- outtt(tp->t_enum->etag, tp->t_enum->etdef);
- } else if (ts == STRUCT || ts == UNION) {
- outtt(tp->t_str->stag, tp->t_str->stdef);
- } else if (ts == FUNC && tp->t_proto) {
- na = 0;
- for (arg = tp->t_args; arg != NULL; arg = arg->s_nxt)
- na++;
- if (tp->t_vararg)
- na++;
- outint(na);
- for (arg = tp->t_args; arg != NULL; arg = arg->s_nxt)
- outtype(arg->s_type);
- if (tp->t_vararg)
- outchar('E');
- }
- tp = tp->t_subt;
- }
-}
-
-/*
- * type to string
- * used for debugging output
- *
- * it uses its own output buffer for conversion
- */
-const char *
-ttos(type_t *tp)
-{
- static ob_t tob;
- ob_t tmp;
-
- if (tob.o_buf == NULL) {
- tob.o_len = 64;
- tob.o_buf = tob.o_nxt = xmalloc(tob.o_len);
- tob.o_end = tob.o_buf + tob.o_len;
- }
-
- tmp = ob;
- ob = tob;
- ob.o_nxt = ob.o_buf;
- outtype(tp);
- outchar('\0');
- tob = ob;
- ob = tmp;
-
- return (tob.o_buf);
-}
-
-/*
- * write the name of a tag or typename
- *
- * if the tag is named, the name of the
- * tag is written, otherwise, if a typename exists which
- * refers to this tag, this typename is written
- */
-static void
-outtt(sym_t *tag, sym_t *tdef)
-{
- if (tag->s_name != unnamed) {
- outint(1);
- outname(tag->s_name);
- } else if (tdef != NULL) {
- outint(2);
- outname(tdef->s_name);
- } else {
- outint(0);
- }
-}
-
-/*
- * write information about an global declared/defined symbol
- * with storage class extern
- *
- * informations about function definitions are written in outfdef(),
- * not here
- */
-void
-outsym(sym_t *sym, scl_t sc, def_t def)
-{
- /*
- * Static function declarations must also be written to the output
- * file. Compatibility of function declarations (for both static
- * and extern functions) must be checked in lint2. Lint1 can't do
- * this, especially not, if functions are declared at block level
- * before their first declaration at level 0.
- */
- if (sc != EXTERN && !(sc == STATIC && sym->s_type->t_tspec == FUNC))
- return;
-
- /* reset buffer */
- outclr();
-
- /*
- * line number of .c source, 'd' for declaration, Id of current
- * source (.c or .h), and line in current source.
- */
- outint(csrc_pos.p_line);
- outchar('d');
- outint(getfnid(sym->s_dpos.p_file));
- outchar('.');
- outint(sym->s_dpos.p_line);
-
- /* flags */
-
- switch (def) {
- case DEF:
- /* defined */
- outchar('d');
- break;
- case TDEF:
- /* tentative defined */
- outchar('t');
- break;
- case DECL:
- /* declared */
- outchar('e');
- break;
- default:
- lerror("outsym() 2");
- }
- if (llibflg && def != DECL) {
- /*
- * mark it as used so we get no warnings from lint2 about
- * unused symbols in libraries.
- */
- outchar('u');
- }
-
- if (sc == STATIC)
- outchar('s');
-
- /* name of the symbol */
- outname(sym->s_name);
-
- /* type of the symbol */
- outtype(sym->s_type);
-}
-
-/*
- * write information about function definition
- *
- * this is also done for static functions so we are able to check if
- * they are called with proper argument types
- */
-void
-outfdef(sym_t *fsym, pos_t *posp, int rval, int osdef, sym_t *args)
-{
- int narg;
- sym_t *arg;
-
- /* reset the buffer */
- outclr();
-
- /*
- * line number of .c source, 'd' for declaration, Id of current
- * source (.c or .h), and line in current source
- *
- * we are already at the end of the function. If we are in the
- * .c source, posp->p_line is correct, otherwise csrc_pos.p_line
- * (for functions defined in header files).
- */
- if (posp->p_file == csrc_pos.p_file) {
- outint(posp->p_line);
- } else {
- outint(csrc_pos.p_line);
- }
- outchar('d');
- outint(getfnid(posp->p_file));
- outchar('.');
- outint(posp->p_line);
-
- /* flags */
-
- /* both SCANFLIKE and PRINTFLIKE imply VARARGS */
- if (prflstrg != -1) {
- nvararg = prflstrg;
- } else if (scflstrg != -1) {
- nvararg = scflstrg;
- }
-
- if (nvararg != -1) {
- outchar('v');
- outint(nvararg);
- }
- if (scflstrg != -1) {
- outchar('S');
- outint(scflstrg);
- }
- if (prflstrg != -1) {
- outchar('P');
- outint(prflstrg);
- }
- nvararg = prflstrg = scflstrg = -1;
-
- outchar('d');
-
- if (rval)
- /* has return value */
- outchar('r');
-
- if (llibflg)
- /*
- * mark it as used so lint2 does not complain about
- * unused symbols in libraries
- */
- outchar('u');
-
- if (osdef)
- /* old style function definition */
- outchar('o');
-
- if (fsym->s_scl == STATIC)
- outchar('s');
-
- /* name of function */
- outname(fsym->s_name);
-
- /* argument types and return value */
- if (osdef) {
- narg = 0;
- for (arg = args; arg != NULL; arg = arg->s_nxt)
- narg++;
- outchar('f');
- outint(narg);
- for (arg = args; arg != NULL; arg = arg->s_nxt)
- outtype(arg->s_type);
- outtype(fsym->s_type->t_subt);
- } else {
- outtype(fsym->s_type);
- }
-}
-
-/*
- * write out all information necessary for lint2 to check function
- * calls
- *
- * rvused is set if the return value is used (asigned to a variable)
- * rvdisc is set if the return value is not used and not ignored
- * (casted to void)
- */
-void
-outcall(tnode_t *tn, int rvused, int rvdisc)
-{
- tnode_t *args, *arg;
- int narg, n, i;
- quad_t q;
- tspec_t t;
-
- /* reset buffer */
- outclr();
-
- /*
- * line number of .c source, 'c' for function call, Id of current
- * source (.c or .h), and line in current source
- */
- outint(csrc_pos.p_line);
- outchar('c');
- outint(getfnid(curr_pos.p_file));
- outchar('.');
- outint(curr_pos.p_line);
-
- /*
- * flags; 'u' and 'i' must be last to make sure a letter
- * is between the numeric argument of a flag and the name of
- * the function
- */
- narg = 0;
- args = tn->tn_right;
- for (arg = args; arg != NULL; arg = arg->tn_right)
- narg++;
- /* informations about arguments */
- for (n = 1; n <= narg; n++) {
- /* the last argument is the top one in the tree */
- for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) ;
- arg = arg->tn_left;
- if (arg->tn_op == CON) {
- if (isityp(t = arg->tn_type->t_tspec)) {
- /*
- * XXX it would probably be better to
- * explicitly test the sign
- */
- if ((q = arg->tn_val->v_quad) == 0) {
- /* zero constant */
- outchar('z');
- } else if (msb(q, t, 0) == 0) {
- /* positive if casted to signed */
- outchar('p');
- } else {
- /* negative if casted to signed */
- outchar('n');
- }
- outint(n);
- }
- } else {
- if (arg->tn_op == CVT && !arg->tn_cast)
- arg = arg->tn_left;
- if (arg->tn_op == AMPER &&
- arg->tn_left->tn_op == STRING &&
- arg->tn_left->tn_strg->st_tspec == CHAR) {
- /* constant string, write format specifiers */
- outchar('s');
- outint(n);
- outfstrg(arg->tn_left->tn_strg);
- }
- }
-
- }
- /* return value discarded/used/ignored */
- outchar(rvdisc ? 'd' : (rvused ? 'u' : 'i'));
-
- /* name of the called function */
- outname(tn->tn_left->tn_left->tn_sym->s_name);
-
- /* types of arguments */
- outchar('f');
- outint(narg);
- for (n = 1; n <= narg; n++) {
- /* the last argument is the top one in the tree */
- for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) ;
- outtype(arg->tn_left->tn_type);
- }
- /* expected type of return value */
- outtype(tn->tn_type);
-}
-
-/*
- * extracts potential format specifiers for printf() and scanf() and
- * writes them, enclosed in "" and quoted if necessary, to the output buffer
- */
-static void
-outfstrg(strg_t *strg)
-{
- int c, oc, first;
- u_char *cp;
-
- if (strg->st_tspec != CHAR)
- lerror("outfstrg() 1");
-
- cp = strg->st_cp;
-
- outchar('"');
-
- c = *cp++;
-
- while (c != '\0') {
-
- if (c != '%') {
- c = *cp++;
- continue;
- }
-
- outqchar('%');
- c = *cp++;
-
- /* flags for printf and scanf and *-fieldwidth for printf */
- while (c != '\0' && (c == '-' || c == '+' || c == ' ' ||
- c == '#' || c == '0' || c == '*')) {
- outqchar(c);
- c = *cp++;
- }
-
- /* numeric field width */
- while (isdigit(c)) {
- outqchar(c);
- c = *cp++;
- }
-
- /* precision for printf */
- if (c == '.') {
- outqchar(c);
- if ((c = *cp++) == '*') {
- outqchar(c);
- c = *cp++;
- } else {
- while (isdigit(c)) {
- outqchar(c);
- c = *cp++;
- }
- }
- }
-
- /* h, l, L and q flags fpr printf and scanf */
- if (c == 'h' || c == 'l' || c == 'L' || c == 'q') {
- outqchar(c);
- c = *cp++;
- }
-
- /*
- * The last character. It is always written so we can detect
- * invalid format specifiers.
- */
- if (c != '\0') {
- outqchar(c);
- oc = c;
- c = *cp++;
- /*
- * handle [ for scanf. [-] means that a minus sign
- * was found at an undefined position.
- */
- if (oc == '[') {
- if (c == '^')
- c = *cp++;
- if (c == ']')
- c = *cp++;
- first = 1;
- while (c != '\0' && c != ']') {
- if (c == '-') {
- if (!first && *cp != ']')
- outqchar(c);
- }
- first = 0;
- c = *cp++;
- }
- if (c == ']') {
- outqchar(c);
- c = *cp++;
- }
- }
- }
-
- }
-
- outchar('"');
-}
-
-/*
- * writes a record if sym was used
- */
-void
-outusg(sym_t *sym)
-{
- /* reset buffer */
- outclr();
-
- /*
- * line number of .c source, 'u' for used, Id of current
- * source (.c or .h), and line in current source
- */
- outint(csrc_pos.p_line);
- outchar('u');
- outint(getfnid(curr_pos.p_file));
- outchar('.');
- outint(curr_pos.p_line);
-
- /* necessary to delimit both numbers */
- outchar('x');
-
- /* Den Namen des Symbols ausgeben */
- outname(sym->s_name);
-}