db_expr.c revision 92756
160484Sobrien/*
278828Sobrien * Mach Operating System
360484Sobrien * Copyright (c) 1991,1990 Carnegie Mellon University
460484Sobrien * All Rights Reserved.
560484Sobrien *
660484Sobrien * Permission to use, copy, modify and distribute this software and its
760484Sobrien * documentation is hereby granted, provided that both the copyright
860484Sobrien * notice and this permission notice appear in all copies of the
960484Sobrien * software, derivative works or modified versions, and any portions
1060484Sobrien * thereof, and that both notices appear in supporting documentation.
1160484Sobrien *
1260484Sobrien * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
1360484Sobrien * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
1460484Sobrien * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1560484Sobrien *
1660484Sobrien * Carnegie Mellon requests users of this software to return to
1760484Sobrien *
1860484Sobrien *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
1960484Sobrien *  School of Computer Science
2060484Sobrien *  Carnegie Mellon University
2160484Sobrien *  Pittsburgh PA 15213-3890
2260484Sobrien *
2360484Sobrien * any improvements or extensions that they make and grant Carnegie the
2460484Sobrien * rights to redistribute these changes.
2560484Sobrien *
2660484Sobrien * $FreeBSD: head/sys/ddb/db_expr.c 92756 2002-03-20 05:14:42Z alfred $
2760484Sobrien */
2860484Sobrien
2960484Sobrien/*
3060484Sobrien *	Author: David B. Golub, Carnegie Mellon University
3177298Sobrien *	Date:	7/90
3260484Sobrien */
3377298Sobrien#include <sys/param.h>
3477298Sobrien
3577298Sobrien#include <ddb/ddb.h>
3677298Sobrien#include <ddb/db_lex.h>
3777298Sobrien#include <ddb/db_access.h>
3877298Sobrien#include <ddb/db_command.h>
3977298Sobrien
4077298Sobrienstatic boolean_t	db_add_expr(db_expr_t *valuep);
4177298Sobrienstatic boolean_t	db_mult_expr(db_expr_t *valuep);
4277298Sobrienstatic boolean_t	db_shift_expr(db_expr_t *valuep);
4377298Sobrienstatic boolean_t	db_term(db_expr_t *valuep);
4477298Sobrienstatic boolean_t	db_unary(db_expr_t *valuep);
4577298Sobrien
4660484Sobrienstatic boolean_t
4760484Sobriendb_term(valuep)
4860484Sobrien	db_expr_t *valuep;
4960484Sobrien{
5060484Sobrien	int	t;
5160484Sobrien
5260484Sobrien	t = db_read_token();
5360484Sobrien	if (t == tIDENT) {
5460484Sobrien	    if (!db_value_of_name(db_tok_string, valuep)) {
5560484Sobrien		db_error("Symbol not found\n");
5660484Sobrien		/*NOTREACHED*/
5760484Sobrien	    }
5860484Sobrien	    return (TRUE);
5960484Sobrien	}
6060484Sobrien	if (t == tNUMBER) {
6160484Sobrien	    *valuep = (db_expr_t)db_tok_number;
6260484Sobrien	    return (TRUE);
6360484Sobrien	}
6460484Sobrien	if (t == tDOT) {
6560484Sobrien	    *valuep = (db_expr_t)db_dot;
6660484Sobrien	    return (TRUE);
6760484Sobrien	}
6860484Sobrien	if (t == tDOTDOT) {
6960484Sobrien	    *valuep = (db_expr_t)db_prev;
7060484Sobrien	    return (TRUE);
7160484Sobrien	}
7260484Sobrien	if (t == tPLUS) {
7360484Sobrien	    *valuep = (db_expr_t) db_next;
7460484Sobrien	    return (TRUE);
7560484Sobrien	}
7660484Sobrien	if (t == tDITTO) {
7760484Sobrien	    *valuep = (db_expr_t)db_last_addr;
7860484Sobrien	    return (TRUE);
7977298Sobrien	}
8060484Sobrien	if (t == tDOLLAR) {
8160484Sobrien	    if (!db_get_variable(valuep))
8260484Sobrien		return (FALSE);
8360484Sobrien	    return (TRUE);
8460484Sobrien	}
8560484Sobrien	if (t == tLPAREN) {
8660484Sobrien	    if (!db_expression(valuep)) {
8760484Sobrien		db_error("Syntax error\n");
8860484Sobrien		/*NOTREACHED*/
8960484Sobrien	    }
9060484Sobrien	    t = db_read_token();
9160484Sobrien	    if (t != tRPAREN) {
9260484Sobrien		db_error("Syntax error\n");
9360484Sobrien		/*NOTREACHED*/
9460484Sobrien	    }
9560484Sobrien	    return (TRUE);
9660484Sobrien	}
9760484Sobrien	db_unread_token(t);
9860484Sobrien	return (FALSE);
9977298Sobrien}
10077298Sobrien
10177298Sobrienstatic boolean_t
10277298Sobriendb_unary(valuep)
10377298Sobrien	db_expr_t *valuep;
10477298Sobrien{
10560484Sobrien	int	t;
10677298Sobrien
10777298Sobrien	t = db_read_token();
10877298Sobrien	if (t == tMINUS) {
10977298Sobrien	    if (!db_unary(valuep)) {
11077298Sobrien		db_error("Syntax error\n");
11177298Sobrien		/*NOTREACHED*/
11260484Sobrien	    }
11377298Sobrien	    *valuep = -*valuep;
11477298Sobrien	    return (TRUE);
11577298Sobrien	}
11677298Sobrien	if (t == tSTAR) {
11777298Sobrien	    /* indirection */
11877298Sobrien	    if (!db_unary(valuep)) {
11977298Sobrien		db_error("Syntax error\n");
12060484Sobrien		/*NOTREACHED*/
12177298Sobrien	    }
12277298Sobrien	    *valuep = db_get_value((db_addr_t)*valuep, sizeof(int), FALSE);
12360484Sobrien	    return (TRUE);
12477298Sobrien	}
12577298Sobrien	db_unread_token(t);
12677298Sobrien	return (db_term(valuep));
12777298Sobrien}
12860484Sobrien
12977298Sobrienstatic boolean_t
13077298Sobriendb_mult_expr(valuep)
13177298Sobrien	db_expr_t *valuep;
13277298Sobrien{
13377298Sobrien	db_expr_t	lhs, rhs;
13477298Sobrien	int		t;
13577298Sobrien
13677298Sobrien	if (!db_unary(&lhs))
13777298Sobrien	    return (FALSE);
13877298Sobrien
13977298Sobrien	t = db_read_token();
14077298Sobrien	while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH) {
14177298Sobrien	    if (!db_term(&rhs)) {
14277298Sobrien		db_error("Syntax error\n");
14377298Sobrien		/*NOTREACHED*/
14477298Sobrien	    }
14577298Sobrien	    if (t == tSTAR)
14677298Sobrien		lhs *= rhs;
14777298Sobrien	    else {
14877298Sobrien		if (rhs == 0) {
14977298Sobrien		    db_error("Divide by 0\n");
15077298Sobrien		    /*NOTREACHED*/
15177298Sobrien		}
15277298Sobrien		if (t == tSLASH)
15377298Sobrien		    lhs /= rhs;
15477298Sobrien		else if (t == tPCT)
15577298Sobrien		    lhs %= rhs;
15677298Sobrien		else
15777298Sobrien		    lhs = ((lhs+rhs-1)/rhs)*rhs;
15877298Sobrien	    }
15977298Sobrien	    t = db_read_token();
16077298Sobrien	}
16177298Sobrien	db_unread_token(t);
16277298Sobrien	*valuep = lhs;
16377298Sobrien	return (TRUE);
16477298Sobrien}
16577298Sobrien
16677298Sobrienstatic boolean_t
16777298Sobriendb_add_expr(valuep)
16877298Sobrien	db_expr_t *valuep;
16977298Sobrien{
17077298Sobrien	db_expr_t	lhs, rhs;
17177298Sobrien	int		t;
17277298Sobrien
17377298Sobrien	if (!db_mult_expr(&lhs))
17477298Sobrien	    return (FALSE);
17577298Sobrien
17677298Sobrien	t = db_read_token();
17777298Sobrien	while (t == tPLUS || t == tMINUS) {
17877298Sobrien	    if (!db_mult_expr(&rhs)) {
17977298Sobrien		db_error("Syntax error\n");
18077298Sobrien		/*NOTREACHED*/
18177298Sobrien	    }
18277298Sobrien	    if (t == tPLUS)
18377298Sobrien		lhs += rhs;
18477298Sobrien	    else
18577298Sobrien		lhs -= rhs;
18677298Sobrien	    t = db_read_token();
18777298Sobrien	}
18877298Sobrien	db_unread_token(t);
18977298Sobrien	*valuep = lhs;
19077298Sobrien	return (TRUE);
19177298Sobrien}
19277298Sobrien
19377298Sobrienstatic boolean_t
19477298Sobriendb_shift_expr(valuep)
19577298Sobrien	db_expr_t *valuep;
19677298Sobrien{
19777298Sobrien	db_expr_t	lhs, rhs;
19877298Sobrien	int		t;
19977298Sobrien
20077298Sobrien	if (!db_add_expr(&lhs))
20177298Sobrien	    return (FALSE);
20260484Sobrien
20377298Sobrien	t = db_read_token();
20477298Sobrien	while (t == tSHIFT_L || t == tSHIFT_R) {
20577298Sobrien	    if (!db_add_expr(&rhs)) {
20677298Sobrien		db_error("Syntax error\n");
20760484Sobrien		/*NOTREACHED*/
20860484Sobrien	    }
20977298Sobrien	    if (rhs < 0) {
21077298Sobrien		db_error("Negative shift amount\n");
21177298Sobrien		/*NOTREACHED*/
21277298Sobrien	    }
21377298Sobrien	    if (t == tSHIFT_L)
21477298Sobrien		lhs <<= rhs;
21560484Sobrien	    else {
21677298Sobrien		/* Shift right is unsigned */
21777298Sobrien		lhs = (unsigned) lhs >> rhs;
21877298Sobrien	    }
21977298Sobrien	    t = db_read_token();
22060484Sobrien	}
22177298Sobrien	db_unread_token(t);
22277298Sobrien	*valuep = lhs;
22360484Sobrien	return (TRUE);
22477298Sobrien}
22560484Sobrien
22677298Sobrienint
22777298Sobriendb_expression(valuep)
22877298Sobrien	db_expr_t *valuep;
22977298Sobrien{
23060484Sobrien	return (db_shift_expr(valuep));
23177298Sobrien}
23277298Sobrien