Example #1
0
/*
 * Print a warning if a definition/declaration does not match another
 * definition/declaration of the same name. For functions, only the
 * types of return values are tested.
 */
static void
chkvtdi(hte_t *hte, sym_t *def, sym_t *decl)
{
    sym_t	*sym;
    type_t	*tp1, *tp2;
    /* LINTED (automatic hides external declaration: warn) */
    int	eq, warn;
    char	*pos1;

    if (def == NULL)
        def = decl;
    if (def == NULL)
        return;

    tp1 = TP(def->s_type);
    for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) {
        if (sym == def)
            continue;
        tp2 = TP(sym->s_type);
        warn = 0;
        if (tp1->t_tspec == FUNC && tp2->t_tspec == FUNC) {
            eq = eqtype(tp1->t_subt, tp2->t_subt, 1, 0, 0, &warn);
        } else {
            eq = eqtype(tp1, tp2, 0, 0, 0, &warn);
        }
        if (!eq || (sflag && warn)) {
            pos1 = xstrdup(mkpos(&def->s_pos));
            /* %s value declared inconsistently\t%s  ::  %s */
            msg(5, hte->h_name, pos1, mkpos(&sym->s_pos));
            free(pos1);
        }
    }
}
Example #2
0
/*
 * Print a warning if there is more than one definition for
 * this name.
 */
static void
chkmd(hte_t *hte)
{
    sym_t	*sym, *def1;
    char	*pos1;

    if (!hte->h_def)
        return;

    def1 = NULL;
    for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) {
        /*
         * ANSI C allows tentative definitions of the same name in
         * only one compilation unit.
         */
        if (sym->s_def != DEF && (!sflag || sym->s_def != TDEF))
            continue;
        if (def1 == NULL) {
            def1 = sym;
            continue;
        }
        pos1 = xstrdup(mkpos(&def1->s_pos));
        /* %s multiply defined\t%s  ::  %s */
        msg(3, hte->h_name, pos1, mkpos(&sym->s_pos));
        free(pos1);
    }
}
Example #3
0
/*
 * Print a warning if the return value assumed for a function call
 * differs from the return value of the function definition or
 * function declaration.
 *
 * If no definition/declaration can be found, the assumed return values
 * are always int. So there is no need to compare with another function
 * call as it's done for function arguments.
 */
static void
chkvtui(hte_t *hte, sym_t *def, sym_t *decl)
{
    fcall_t	*call;
    char	*pos1;
    type_t	*tp1, *tp2;
    /* LINTED (automatic hides external declaration: warn) */
    int	warn, eq;
    tspec_t	t1;

    if (hte->h_calls == NULL)
        return;

    if (def == NULL)
        def = decl;
    if (def == NULL)
        return;

    t1 = (tp1 = TP(def->s_type)->t_subt)->t_tspec;
    for (call = hte->h_calls; call != NULL; call = call->f_nxt) {
        tp2 = TP(call->f_type)->t_subt;
        eq = eqtype(tp1, tp2, 1, 0, 0, (warn = 0, &warn));
        if (!call->f_rused) {
            /* no return value used */
            if ((t1 == STRUCT || t1 == UNION) && !eq) {
                /*
                 * If a function returns a struct or union it
                 * must be declared to return a struct or
                 * union, also if the return value is ignored.
                 * This is necessary because the caller must
                 * allocate stack space for the return value.
                 * If it does not, the return value would over-
                 * write other data.
                 * XXX Following massage may be confusing
                 * because it appears also if the return value
                 * was declared inconsistently. But this
                 * behaviour matches pcc based lint, so it is
                 * accepted for now.
                 */
                pos1 = xstrdup(mkpos(&def->s_pos));
                /* %s value must be decl. before use %s :: %s */
                msg(17, hte->h_name,
                    pos1, mkpos(&call->f_pos));
                free(pos1);
            }
            continue;
        }
        if (!eq || (sflag && warn)) {
            pos1 = xstrdup(mkpos(&def->s_pos));
            /* %s value used inconsistenty\t%s  ::  %s */
            msg(4, hte->h_name, pos1, mkpos(&call->f_pos));
            free(pos1);
        }
    }
}
Example #4
0
static void
tomanyarg(hte_t *hte, fcall_t *call)
{

    /* %s: too many args for format  \t%s */
    msg(16, hte->h_name, mkpos(&call->f_pos));
}
Example #5
0
static void
inconarg(hte_t *hte, fcall_t *call, int n)
{

    /* %s, arg %d inconsistent with format\t%s(%d) */
    msg(14, hte->h_name, n, mkpos(&call->f_pos));
}
Example #6
0
static void
badfmt(hte_t *hte, fcall_t *call)
{

    /* %s: malformed format string\t%s */
    msg(13, hte->h_name, mkpos(&call->f_pos));
}
Example #7
0
/*
 * Print a warning if the name has been used, but not defined.
 */
static void
chkund(hte_t *hte)
{
    fcall_t	*fcall;
    usym_t	*usym;

    if (!hte->h_used || hte->h_def)
        return;

    if ((fcall = hte->h_calls) != NULL) {
        /* %s used( %s ), but not defined */
        msg(0, hte->h_name, mkpos(&fcall->f_pos));
    } else if ((usym = hte->h_usyms) != NULL) {
        /* %s used( %s ), but not defined */
        msg(0, hte->h_name, mkpos(&usym->u_pos));
    }
}
Example #8
0
/*
 * Print a warning if the name has been defined, but never used.
 */
static void
chkdnu(hte_t *hte)
{
    sym_t	*sym;

    if (!hte->h_def || hte->h_used)
        return;

    for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) {
        if (sym->s_def == DEF || sym->s_def == TDEF) {
            /* %s defined( %s ), but never used */
            msg(1, hte->h_name, mkpos(&sym->s_pos));
            break;
        }
    }
}
Example #9
0
/*
 * Print a warning if the variable has been declared, but is not used
 * or defined.
 */
static void
chkdnud(hte_t *hte)
{
    sym_t	*sym;

    if (hte->h_syms == NULL || hte->h_used || hte->h_def)
        return;

    sym = hte->h_syms;
    if (TP(sym->s_type)->t_tspec == FUNC)
        return;

    if (sym->s_def != DECL)
        errx(1, "internal error: chkdnud() 1");
    /* %s declared( %s ), but never used or defined */
    msg(2, hte->h_name, mkpos(&sym->s_pos));
}
Example #10
0
/*
 * Print warnings for return values which are used, but not returned,
 * or return values which are always or sometimes ignored.
 */
static void
chkrvu(hte_t *hte, sym_t *def)
{
    fcall_t	*call;
    int	used, ignored;

    if (def == NULL)
        /* don't know wheter or not the functions returns a value */
        return;

    if (hte->h_calls == NULL)
        return;

    if (def->s_rval) {
        /* function has return value */
        used = ignored = 0;
        for (call = hte->h_calls; call != NULL; call = call->f_nxt) {
            used |= call->f_rused || call->f_rdisc;
            ignored |= !call->f_rused && !call->f_rdisc;
        }
        /*
         * XXX as soon as we are able to disable single warnings
         * the following dependencies from hflag should be removed.
         * but for now I do'nt want to be botherd by this warnings
         * which are almost always useless.
         */
        if (!used && ignored) {
            if (hflag)
                /* %s returns value which is always ignored */
                msg(8, hte->h_name);
        } else if (used && ignored) {
            if (hflag)
                /* %s returns value which is sometimes ign. */
                msg(9, hte->h_name);
        }
    } else {
        /* function has no return value */
        for (call = hte->h_calls; call != NULL; call = call->f_nxt) {
            if (call->f_rused)
                /* %s value is used( %s ), but none ret. */
                msg(10, hte->h_name, mkpos(&call->f_pos));
        }
    }
}
Example #11
0
/*
 * Check a single argument in a function call.
 *
 *  hte		a pointer to the hash table entry of the function
 *  n		the number of the argument (1..)
 *  def		the function definition or NULL
 *  decl	prototype declaration, old style declaration or NULL
 *  pos1p	position of definition, declaration of first call
 *  call1	first call, if both def and decl are old style def/decl
 *  call	checked call
 *  arg1	currently checked argument of def/decl/call1
 *  arg2	currently checked argument of call
 *
 */
static void
chkau(hte_t *hte, int n, sym_t *def, sym_t *decl, pos_t *pos1p,
      fcall_t *call1, fcall_t *call, type_t *arg1, type_t *arg2)
{
    /* LINTED (automatic hides external declaration: warn) */
    int	promote, asgn, warn;
    tspec_t	t1, t2;
    arginf_t *ai, *ai1;
    char	*pos1;

    /*
     * If a function definition is available (def != NULL), we compare the
     * function call (call) with the definition. Otherwise, if a function
     * definition is available and it is not an old style definition
     * (decl != NULL && TP(decl->s_type)->t_proto), we compare the call
     * with this declaration. Otherwise we compare it with the first
     * call we have found (call1).
     */

    /* arg1 must be promoted if it stems from an old style definition */
    promote = def != NULL && def->s_osdef;

    /*
     * If we compair with a definition or declaration, we must perform
     * the same checks for qualifiers in indirected types as in
     * assignments.
     */
    asgn = def != NULL || (decl != NULL && TP(decl->s_type)->t_proto);

    warn = 0;
    if (eqtype(arg1, arg2, 1, promote, asgn, &warn) && (!sflag || !warn))
        return;

    /*
     * Other lint implementations print warnings as soon as the type
     * of an argument does not match exactly the expected type. The
     * result are lots of warnings which are really not necessary.
     * We print a warning only if
     *   (0) at least one type is not an integer type and types differ
     *   (1) hflag is set and types differ
     *   (2) types differ, except in signedness
     * If the argument is an integer constant whose msb is not set,
     * signedness is ignored (e.g. 0 matches both signed and unsigned
     * int). This is with and without hflag.
     * If the argument is an integer constant with value 0 and the
     * expected argument is of type pointer and the width of the
     * integer constant is the same as the width of the pointer,
     * no warning is printed.
     */
    t1 = arg1->t_tspec;
    t2 = arg2->t_tspec;
    if (isityp(t1) && isityp(t2) && !arg1->t_isenum && !arg2->t_isenum) {
        if (promote) {
            /*
             * XXX Here is a problem: Although it is possible to
             * pass an int where a char/short it expected, there
             * may be loss in significant digits. We should first
             * check for const arguments if they can be converted
             * into the original parameter type.
             */
            if (t1 == FLOAT) {
                t1 = DOUBLE;
            } else if (t1 == CHAR || t1 == SCHAR) {
                t1 = INT;
            } else if (t1 == UCHAR) {
                t1 = tflag ? UINT : INT;
            } else if (t1 == SHORT) {
                t1 = INT;
            } else if (t1 == USHORT) {
                /* CONSTCOND */
                t1 = INT_MAX < USHRT_MAX || tflag ? UINT : INT;
            }
        }

        if (styp(t1) == styp(t2)) {

            /*
             * types differ only in signedness; get information
             * about arguments
             */

            /*
             * treat a definition like a call with variable
             * arguments
             */
            ai1 = call1 != NULL ? call1->f_args : NULL;

            /*
             * if two calls are compared, ai1 is set to the
             * information for the n-th argument, if this was
             * a constant, otherwise to NULL
             */
            for ( ; ai1 != NULL; ai1 = ai1->a_nxt) {
                if (ai1->a_num == n)
                    break;
            }
            /*
             * ai is set to the information of the n-th arg
             * of the (second) call, if this was a constant,
             * otherwise to NULL
             */
            for (ai = call->f_args; ai != NULL; ai = ai->a_nxt) {
                if (ai->a_num == n)
                    break;
            }

            if (ai1 == NULL && ai == NULL) {
                /* no constant at all */
                if (!hflag)
                    return;
            } else if (ai1 == NULL || ai == NULL) {
                /* one constant */
                if (ai == NULL)
                    ai = ai1;
                if (ai->a_zero || ai->a_pcon)
                    /* same value in signed and unsigned */
                    return;
                /* value (not representation) differently */
            } else {
                /*
                 * two constants, one signed, one unsigned;
                 * if the msb of one of the constants is set,
                 * the argument is used inconsistently.
                 */
                if (!ai1->a_ncon && !ai->a_ncon)
                    return;
            }
        }

    } else if (t1 == PTR && isityp(t2)) {
        for (ai = call->f_args; ai != NULL; ai = ai->a_nxt) {
            if (ai->a_num == n)
                break;
        }
        /*
         * Vendor implementations of lint (e.g. HP-UX, Digital UNIX)
         * don't care about the size of the integer argument,
         * only whether or not it is zero.  We do the same.
         */
        if (ai != NULL && ai->a_zero)
            return;
    }

    pos1 = xstrdup(mkpos(pos1p));
    /* %s, arg %d used inconsistently\t%s  ::  %s */
    msg(6, hte->h_name, n, pos1, mkpos(&call->f_pos));
    free(pos1);
}
Example #12
0
/*
 * Print a warning if a function is called with arguments which does
 * not match the function definition, declaration or another call
 * of the same function.
 */
static void
chkfaui(hte_t *hte, sym_t *def, sym_t *decl)
{
    type_t	*tp1, *tp2, **ap1, **ap2;
    pos_t	*pos1p = NULL;
    fcall_t	*calls, *call, *call1;
    int	n, as;
    char	*pos1;
    arginf_t *ai;

    if ((calls = hte->h_calls) == NULL)
        return;

    /*
     * If we find a function definition, we use this for comparison,
     * otherwise the first prototype we can find. If there is no
     * definition or prototype declaration, the first function call
     * is used.
     */
    tp1 = NULL;
    call1 = NULL;
    if (def != NULL) {
        if ((tp1 = TP(def->s_type))->t_tspec != FUNC)
            return;
        pos1p = &def->s_pos;
    } else if (decl != NULL && TP(decl->s_type)->t_proto) {
        if ((tp1 = TP(decl->s_type))->t_tspec != FUNC)
            return;
        pos1p = &decl->s_pos;
    }
    if (tp1 == NULL) {
        call1 = calls;
        calls = calls->f_nxt;
        if ((tp1 = TP(call1->f_type))->t_tspec != FUNC)
            return;
        pos1p = &call1->f_pos;
    }

    n = 1;
    for (call = calls; call != NULL; call = call->f_nxt) {
        if ((tp2 = TP(call->f_type))->t_tspec != FUNC)
            continue;
        ap1 = tp1->t_args;
        ap2 = tp2->t_args;
        n = 0;
        while (*ap1 != NULL && *ap2 != NULL) {
            if (def != NULL && def->s_va && n >= def->s_nva)
                break;
            n++;
            chkau(hte, n, def, decl, pos1p, call1, call,
                  *ap1, *ap2);
            ap1++;
            ap2++;
        }
        if (*ap1 == *ap2) {
            /* equal # of arguments */
        } else if (def != NULL && def->s_va && n >= def->s_nva) {
            /*
             * function definition with VARARGS; The # of
             * arguments of the call must be at least as large
             * as the parameter of VARARGS.
             */
        } else if (*ap2 != NULL && tp1->t_proto && tp1->t_vararg) {
            /*
             * prototype with ... and function call with
             * at least the same # of arguments as declared
             * in the prototype.
             */
        } else {
            pos1 = xstrdup(mkpos(pos1p));
            /* %s: variable # of args\t%s  ::  %s */
            msg(7, hte->h_name, pos1, mkpos(&call->f_pos));
            free(pos1);
            continue;
        }

        /* perform SCANFLIKE/PRINTFLIKE tests */
        if (def == NULL || (!def->s_prfl && !def->s_scfl))
            continue;
        as = def->s_prfl ? def->s_nprfl : def->s_nscfl;
        for (ai = call->f_args; ai != NULL; ai = ai->a_nxt) {
            if (ai->a_num == as)
                break;
        }
        if (ai == NULL || !ai->a_fmt)
            continue;
        if (def->s_prfl) {
            printflike(hte, call, n, ai->a_fstrg, ap2);
        } else {
            scanflike(hte, call, n, ai->a_fstrg, ap2);
        }
    }
}
Example #13
0
/*
 * Print warnings for inconsistent argument declarations.
 */
static void
chkadecl(hte_t *hte, sym_t *def, sym_t *decl)
{
    /* LINTED (automatic hides external declaration: warn) */
    int	osdef, eq, warn, n;
    sym_t	*sym1, *sym;
    type_t	**ap1, **ap2, *tp1, *tp2;
    char	*pos1;
    const	char *pos2;

    osdef = 0;
    if (def != NULL) {
        osdef = def->s_osdef;
        sym1 = def;
    } else if (decl != NULL && TP(decl->s_type)->t_proto) {
        sym1 = decl;
    } else {
        return;
    }
    if (TP(sym1->s_type)->t_tspec != FUNC)
        return;

    /*
     * XXX Prototypes should also be compared with old style function
     * declarations.
     */

    for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) {
        if (sym == sym1 || !TP(sym->s_type)->t_proto)
            continue;
        ap1 = TP(sym1->s_type)->t_args;
        ap2 = TP(sym->s_type)->t_args;
        n = 0;
        while (*ap1 != NULL && *ap2 != NULL) {
            warn = 0;
            eq = eqtype(*ap1, *ap2, 1, osdef, 0, &warn);
            if (!eq || warn) {
                pos1 = xstrdup(mkpos(&sym1->s_pos));
                pos2 = mkpos(&sym->s_pos);
                /* %s, arg %d declared inconsistently ... */
                msg(11, hte->h_name, n + 1, pos1, pos2);
                free(pos1);
            }
            n++;
            ap1++;
            ap2++;
        }
        if (*ap1 == *ap2) {
            tp1 = TP(sym1->s_type);
            tp2 = TP(sym->s_type);
            if (tp1->t_vararg == tp2->t_vararg)
                continue;
            if (tp2->t_vararg &&
                    sym1->s_va && sym1->s_nva == n && !sflag) {
                continue;
            }
        }
        /* %s: variable # of args declared\t%s  ::  %s */
        pos1 = xstrdup(mkpos(&sym1->s_pos));
        msg(12, hte->h_name, pos1, mkpos(&sym->s_pos));
        free(pos1);
    }
}
Example #14
0
void test(bool* result)
{
    SCREEN_Screen scr;

    scr = screen(80, 25);
    update(result, tposeq("initial cursor", mkpos(0, 0), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(5, 10));
    update(result, tposeq("cursor_address", mkpos(5, 10), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(12, 5));
    carriage_return(&scr);
    update(result, tposeq("carriage_return", mkpos(0, 5), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(12, 5));
    newline(&scr);
    update(result, tposeq("newline", mkpos(0, 6), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(10, 6));
    tab(&scr);
    update(result, tposeq("tab", mkpos(16, 6), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(1, 6));
    column_address(&scr, 16);
    update(result, tposeq("column_address", mkpos(16, 6), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(16, 6));
    row_address(&scr, 12);
    update(result, tposeq("row_address", mkpos(16, 12), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(15, 6));
    cursor_down(&scr);
    update(result, tposeq("cursor_down", mkpos(15, 7), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(15, 6));
    cursor_home(&scr);
    update(result, tposeq("cursor_home", mkpos(0, 0), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(6, 8));
    cursor_left(&scr);
    update(result, tposeq("cursor_left", mkpos(5, 8), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(6, 8));
    cursor_right(&scr);
    update(result, tposeq("cursor_right", mkpos(7, 8), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(6, 8));
    cursor_to_ll(&scr);
    update(result, tposeq("cursor_to_ll", mkpos(0, 24), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(6, 8));
    cursor_up(&scr);
    update(result, tposeq("cursor_up", mkpos(6, 7), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(26, 9));
    parm_left_cursor(&scr, 23);
    update(result, tposeq("parm_left_cursor", mkpos(3, 9), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(3, 9));
    parm_right_cursor(&scr, 23);
    update(result, tposeq("parm_right_cursor", mkpos(26, 9), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(26, 4));
    parm_down_cursor(&scr, 11);
    update(result, tposeq("parm_down_cursor", mkpos(26, 15), cursor(&scr)));

    scr = screen(6, 4);
    cursor_address(&scr, mkpos(2, 3));
    put_char(&scr, 'a');
    SCREEN_Cell want_0 = {'a', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("put_char puts", want_0, cellat(&scr, mkpos(2,3))));

    scr = screen(6, 4);
    cursor_address(&scr, mkpos(2, 3));
    put_char(&scr, 'a');
    update(result, tposeq("put_char moves", mkpos(3, 3), cursor(&scr)));

    scr = screen(6, 4);
    cursor_address(&scr, mkpos(5, 1));
    put_char(&scr, 'a');
    update(result, tposeq("put_char am", mkpos(0, 2), cursor(&scr)));

    scr = screen(6, 4);
    put_chars(&scr, "abcdefGHIJKLmno");
    SCREEN_Cell want_1 = {'J', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("put_char multiple", want_1, cellat(&scr, mkpos(3,1))));

    scr = screen(6, 4);
    put_chars(&scr, "abcdefGHIJKLmno");
    clear_screen(&scr);
    update(result, tposeq("clear_screen homes", mkpos(0, 0), cursor(&scr)));

    scr = screen(6, 4);
    put_chars(&scr, "abcdefGHIJKLmno");
    clear_screen(&scr);
    SCREEN_Cell want_2 = {' ', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("clear_screen clears", want_2, cellat(&scr, mkpos(3,1))));

    scr = screen(6, 4);
    cursor_address(&scr, mkpos(0, 3));
    put_chars(&scr, "abcdefGHIJKLmno");
    SCREEN_Cell want_3 = {'J', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("put_char scrolls at end", want_3, cellat(&scr, mkpos(3,2))));

    scr = screen(6, 3);
    put_chars(&scr, "abcdefGHIJKLmno");
    cursor_home(&scr);
    clr_eos(&scr);
    SCREEN_Cell want_4 = {' ', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("put_char scrolls at end", want_4, cellat(&scr, mkpos(4,1))));
    
    scr = screen(6, 4);
    cursor_down(&scr);
    put_chars(&scr, "abcdefGHIJKLmno");
    cursor_address(&scr, mkpos(0, 3));
    newline(&scr);
    SCREEN_Cell want_5 = {'K', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("newline at bottom scrolls", want_5, cellat(&scr, mkpos(4,1))));

    scr = screen(6, 4);
    put_chars(&scr, "abcdefGHIJKLmno");
    cursor_address(&scr, mkpos(0, 0));
    insert_line(&scr);
    SCREEN_Cell want_6 = {' ', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("insert_line clears full line", want_6, cellat(&scr, mkpos(5,0))));

    scr = screen(24, 4);
    cursor_address(&scr, mkpos(20, 1));
    tab(&scr);
    update(result, tposeq("tab at eol", mkpos(0, 2), cursor(&scr)));
}
Example #15
0
void outputter(SCREEN_Screen* scr, int terminator, GetCharFunction getf)
{
    while (1) {
        unsigned char c = getf();
        if (c == terminator) {
            return;
        }

        switch (c) {
            case '\a': break;   // TODO: alert?
            case '\t': tab(scr); break;
            case '\n': cursor_down(scr); break;
            case '\b': cursor_left(scr); break;
            case '\r': carriage_return(scr); break;
            case 0x1b: 
            {
                c = getf();
                switch (c) {
                    case '[':
                    {
                        int x;
                        if (getnum(getf, &x, &c)) {
                            if (x == 1 && c == 'K') {
                                clr_bol(scr);
                            } else {
                                switch (c) {
                                    case 'm': mode(scr, x); break;
                                    case 'A': parm_up_cursor(scr, x); break;
                                    case 'B': parm_down_cursor(scr, x); break;
                                    case 'C': parm_right_cursor(scr, x); break;
                                    case 'D': parm_left_cursor(scr, x); break;
                                    case 'G': column_address(scr, (x-1)); break;
                                    case 'L': parm_insert_line(scr, x); break;
                                    case 'M': parm_delete_line(scr, x); break;
                                    case 'P': parm_dch(scr, x); break;
                                    case 'S': parm_index(scr, x); break;
                                    case 'T': parm_rindex(scr, x); break;
                                    case 'X': erase_chars(scr, x); break;
                                    case '@': parm_ich(scr, x); break;
                                    case 'd': row_address(scr, (x-1)); break;
                                    case ';':
                                    {
                                        int y;
                                        if (getnum(getf, &y, &c)) {
                                            switch (c) {
                                                case 'm':
                                                    mode(scr, x);
                                                    mode(scr, y);
                                                    break;

                                                case 'H': cursor_address(scr, mkpos(y-1, x-1)); break;
                                                default: 
                                                    fprintf(stderr, "unhandled: ESC[%i;%i%c\n", x, y, c);
                                                    break;
                                            }
                                        } else {
                                            fprintf(stderr, "unhandled: ESC[%i;%c\n", x, c);
                                        }
                                    } break;

                                    default:
                                        fprintf(stderr, "unahndled: ESC[%i%c\n", x, c);
                                        break;
                                }
                            }
                        } else {
                            switch (c) {
                                case '@': insert_character(scr); break;
                                case 'A': cursor_up(scr); break;
                                case 'B': cursor_down(scr); break;
                                case 'C': cursor_right(scr); break;
                                case 'D': cursor_left(scr); break;
                                case 'H': cursor_home(scr); break;
                                case 'I': tab(scr); break;
                                case 'J': clr_eos(scr); break;
                                case 'K': clr_eol(scr); break;
                                case 'L': insert_line(scr); break;
                                case 'M': delete_line(scr); break;
                                case 'P': delete_character(scr); break;
                                case 'm': exit_attribute_mode(scr); break;
                                default:
                                    fprintf(stderr, "unhandled: ESC[%c\n", c);
                                    break;
                            }
                        }

                    } break;

                    case 'M':
                        scroll_reverse(scr);
                        break;

                    default:
                        fprintf(stderr, "unhandled: ESC%c\n", c);
                        break;
                }
            } break;

            default:
            {
                wchar_t wc;
                if ((c & 0x80) == 0x00) {
                    wc = c;
                } else if ((c & 0xE0) == 0xC0) {
                    char c1 = 0x1F & c;
                    char c2 = 0x3F & getf();
                    wc = (c1 << 6) | c2;
                } else if ((c & 0xF0) == 0xE0) {
                    char c1 = 0x0F & c;
                    char c2 = 0x3F & getf();
                    char c3 = 0x3F & getf();
                    wc = (c1 << 12) | (c2 << 6) | c3;
                } else if ((c & 0xF8) == 0xF0) {
                    char c1 = 0x07 & c;
                    char c2 = 0x3F & getf();
                    char c3 = 0x3F & getf();
                    char c4 = 0x3F & getf();
                    wc = (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
                } else if ((c & 0xFC) == 0xF8) {
                    char c1 = 0x03 & c;
                    char c2 = 0x3F & getf();
                    char c3 = 0x3F & getf();
                    char c4 = 0x3F & getf();
                    char c5 = 0x3F & getf();
                    wc = (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | c5;
                } else if ((c & 0xFE) == 0xFC) {
                    char c1 = 0x01 & c;
                    char c2 = 0x3F & getf();
                    char c3 = 0x3F & getf();
                    char c4 = 0x3F & getf();
                    char c5 = 0x3F & getf();
                    char c6 = 0x3F & getf();
                    wc = (c1 << 30) | (c2 << 24) | (c3 << 18) | (c4 << 12) | (c5 < 6) | c6;
                } else {
                    fprintf(stderr, "bad utf-8 sequence: c=0x%02x\n", c);
                    wc = '\0';
                }

                put_char(scr, wc);
            } break;
        }
    }
}
Example #16
0
/*
 * Process a declaration or definition (d-record).
 */
static void
decldef(pos_t *posp, const char *cp)
{
	sym_t	*symp, sym;
	char	c, *ep, *pos1;
	int	used, renamed;
	hte_t	*hte, *renamehte = NULL;
	const char *name, *rename;

	(void)memset(&sym, 0, sizeof (sym));
	STRUCT_ASSIGN(sym.s_pos, *posp);
	sym.s_def = NODECL;

	used = 0;

	while (strchr("tdeurosvPS", (c = *cp)) != NULL) {
		cp++;
		switch (c) {
		case 't':
			if (sym.s_def != NODECL)
				inperr();
			sym.s_def = TDEF;
			break;
		case 'd':
			if (sym.s_def != NODECL)
				inperr();
			sym.s_def = DEF;
			break;
		case 'e':
			if (sym.s_def != NODECL)
				inperr();
			sym.s_def = DECL;
			break;
		case 'u':
			if (used)
				inperr();
			used = 1;
			break;
		case 'r':
			if (sym.s_rval)
				inperr();
			sym.s_rval = 1;
			break;
		case 'o':
			if (sym.s_osdef)
				inperr();
			sym.s_osdef = 1;
			break;
		case 's':
			if (sym.s_static)
				inperr();
			sym.s_static = 1;
			break;
		case 'v':
			if (sym.s_va)
				inperr();
			sym.s_va = 1;
			sym.s_nva = (short)strtol(cp, &ep, 10);
			if (cp == ep)
				inperr();
			cp = ep;
			break;
		case 'P':
			if (sym.s_prfl)
				inperr();
			sym.s_prfl = 1;
			sym.s_nprfl = (short)strtol(cp, &ep, 10);
			if (cp == ep)
				inperr();
			cp = ep;
			break;
		case 'S':
			if (sym.s_scfl)
				inperr();
			sym.s_scfl = 1;
			sym.s_nscfl = (short)strtol(cp, &ep, 10);
			if (cp == ep)
				inperr();
			cp = ep;
			break;
		}
	}

	/* read symbol name, doing renaming if necessary */
	name = inpname(cp, &cp);
	renamed = 0;
	if (*cp == 'r') {
		cp++;
		name = xstrdup(name);
		rename = inpname(cp, &cp);

		/* enter it and see if it's already been renamed */
		renamehte = _hsearch(renametab, name, 1);
		if (renamehte->h_hte == NULL) {
			hte = hsearch(rename, 1);
			renamehte->h_hte = hte;
			renamed = 1;
		} else if (strcmp((hte = renamehte->h_hte)->h_name, rename)) {
			pos1 = xstrdup(mkpos(&renamehte->h_syms->s_pos));
			/* %s renamed multiple times\t%s  ::  %s */
			msg(18, name, pos1, mkpos(&sym.s_pos));
			free(pos1);
		}
		free((char *)name);
	} else {
		/* it might be a previously-done rename */
		hte = _hsearch(renametab, name, 0);
		if (hte != NULL)
			hte = hte->h_hte;
		else
			hte = hsearch(name, 1);
	}
	hte->h_used |= used;
	if (sym.s_def == DEF || sym.s_def == TDEF)
		hte->h_def = 1;

	sym.s_type = inptype(cp, &cp);

	/*
	 * Allocate memory for this symbol only if it was not already
	 * declared or tentatively defined at the same location with
	 * the same type. Works only for symbols with external linkage,
	 * because static symbols, tentatively defined at the same location
	 * but in different translation units are really different symbols.
	 */
	for (symp = hte->h_syms; symp != NULL; symp = symp->s_nxt) {
		if (symp->s_pos.p_isrc == sym.s_pos.p_isrc &&
		    symp->s_pos.p_iline == sym.s_pos.p_iline &&
		    symp->s_type == sym.s_type &&
		    ((symp->s_def == DECL && sym.s_def == DECL) ||
		     (!sflag && symp->s_def == TDEF && sym.s_def == TDEF)) &&
		    !symp->s_static && !sym.s_static) {
			break;
		}
	}

	if (symp == NULL) {
		/* allocsym reserviert keinen Platz fuer s_nva */
		if (sym.s_va || sym.s_prfl || sym.s_scfl) {
			symp = xalloc(sizeof (sym_t));
			STRUCT_ASSIGN(*symp, sym);
		} else {
			symp = xalloc(sizeof (symp->s_s));
			STRUCT_ASSIGN(symp->s_s, sym.s_s);
		}
		*hte->h_lsym = symp;
		hte->h_lsym = &symp->s_nxt;

		/* XXX hack so we can remember where a symbol was renamed */
		if (renamed)
			renamehte->h_syms = symp;
	}

	if (*cp != '\0')
		inperr();
}