FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_cond.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: db_cond.c,v $
29 * Revision 2.5 93/11/17 16:21:26 dbg
30 * Added ANSI function prototypes.
31 * [93/10/08 dbg]
32 *
33 * Revision 2.4 92/08/03 17:30:53 jfriedl
34 * removed silly prototypes
35 * [92/08/02 jfriedl]
36 *
37 * Revision 2.3 92/05/21 17:06:39 jfriedl
38 * Changed errant call of db_error in db_cond_cmd() to db_printf/db_error.
39 * [92/05/20 jfriedl]
40 *
41 * Revision 2.2 91/10/09 15:59:09 af
42 * Created to support conditional break point and command execution.
43 * [91/08/29 tak]
44 *
45 */
46
47 #include <machine/db_machdep.h>
48 #include <machine/setjmp.h>
49
50 #include <ddb/db_lex.h>
51 #include <ddb/db_break.h>
52 #include <ddb/db_command.h>
53 #include <ddb/db_output.h>
54
55
56
57 #define DB_MAX_COND 10 /* maximum conditions to be set */
58
59 int db_ncond_free = DB_MAX_COND; /* free condition */
60 struct db_cond {
61 int c_size; /* size of cond */
62 char c_cond_cmd[DB_LEX_LINE_SIZE]; /* cond & cmd */
63 } db_cond[DB_MAX_COND];
64
65 void
66 db_cond_free(
67 db_thread_breakpoint_t bkpt)
68 {
69 if (bkpt->tb_cond > 0) {
70 db_cond[bkpt->tb_cond-1].c_size = 0;
71 db_ncond_free++;
72 bkpt->tb_cond = 0;
73 }
74 }
75
76 boolean_t
77 db_cond_check(
78 db_thread_breakpoint_t bkpt)
79 {
80 register struct db_cond *cp;
81 db_expr_t value;
82 int t;
83 jmp_buf_t db_jmpbuf;
84
85 if (bkpt->tb_cond <= 0) /* no condition */
86 return TRUE;
87 db_dot = PC_REGS(DDB_REGS);
88 db_prev = db_dot;
89 db_next = db_dot;
90 if (_setjmp(db_recover = &db_jmpbuf)) {
91 /*
92 * in case of error, return true to enter interactive mode
93 */
94 return TRUE;
95 }
96
97 /*
98 * switch input, and evaluate condition
99 */
100 cp = &db_cond[bkpt->tb_cond - 1];
101 db_switch_input(cp->c_cond_cmd, cp->c_size);
102 if (!db_expression(&value)) {
103 db_printf("error: condition evaluation error\n");
104 return TRUE;
105 }
106 if (value == 0 || --(bkpt->tb_count) > 0)
107 return FALSE;
108
109 /*
110 * execute a command list if exist
111 */
112 bkpt->tb_count = bkpt->tb_init_count;
113 if ((t = db_read_token()) != tEOL) {
114 db_unread_token(t);
115 return(db_exec_cmd_nest(0, 0));
116 }
117 return TRUE;
118 }
119
120 void
121 db_cond_print(
122 db_thread_breakpoint_t bkpt)
123 {
124 register char *p, *ep;
125 register struct db_cond *cp;
126
127 if (bkpt->tb_cond <= 0)
128 return;
129 cp = &db_cond[bkpt->tb_cond-1];
130 p = cp->c_cond_cmd;
131 ep = p + cp->c_size;
132 while (p < ep) {
133 if (*p == '\n' || *p == 0)
134 break;
135 db_putchar(*p++);
136 }
137 }
138
139 void
140 db_cond_cmd()
141 {
142 register c;
143 register struct db_cond *cp;
144 register char *p;
145 db_expr_t value;
146 db_thread_breakpoint_t bkpt;
147
148 if (db_read_token() != tHASH || db_read_token() != tNUMBER) {
149 db_printf("#<number> expected instead of \"%s\"\n", db_tok_string);
150 db_error(0);
151 return;
152 }
153 if ((bkpt = db_find_breakpoint_number(db_tok_number, 0)) == 0) {
154 db_printf("No such break point #%d\n", db_tok_number);
155 db_error(0);
156 return;
157 }
158 /*
159 * if the break point already has a condition, free it first
160 */
161 if (bkpt->tb_cond > 0) {
162 cp = &db_cond[bkpt->tb_cond - 1];
163 db_cond_free(bkpt);
164 } else {
165 if (db_ncond_free <= 0) {
166 db_error("Too many conditions\n");
167 return;
168 }
169 for (cp = db_cond; cp < &db_cond[DB_MAX_COND]; cp++)
170 if (cp->c_size == 0)
171 break;
172 if (cp >= &db_cond[DB_MAX_COND])
173 panic("bad db_cond_free");
174 }
175 for (c = db_read_char(); c == ' ' || c == '\t'; c = db_read_char());
176 for (p = cp->c_cond_cmd; c >= 0; c = db_read_char())
177 *p++ = c;
178 /*
179 * switch to saved data and call db_expression to check the condition.
180 * If no condition is supplied, db_expression will return false.
181 * In this case, clear previous condition of the break point.
182 * If condition is supplied, set the condition to the permanent area.
183 * Note: db_expression will not return here, if the condition
184 * expression is wrong.
185 */
186 db_switch_input(cp->c_cond_cmd, p - cp->c_cond_cmd);
187 if (!db_expression(&value)) {
188 /* since condition is already freed, do nothing */
189 db_flush_lex();
190 return;
191 }
192 db_flush_lex();
193 db_ncond_free--;
194 cp->c_size = p - cp->c_cond_cmd;
195 bkpt->tb_cond = (cp - db_cond) + 1;
196 }
Cache object: 22c0557fc69e65294c60bcee21e32006
|