FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_cond.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 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.4 92/08/03 17:30:53 jfriedl
30 * removed silly prototypes
31 * [92/08/02 jfriedl]
32 *
33 * Revision 2.3 92/05/21 17:06:39 jfriedl
34 * Changed errant call of db_error in db_cond_cmd() to db_printf/db_error.
35 * [92/05/20 jfriedl]
36 *
37 * Revision 2.2 91/10/09 15:59:09 af
38 *
39 * Revision 2.1.3.1 91/10/05 13:05:38 jeffreyh
40 * Created to support conditional break point and command execution.
41 * [91/08/29 tak]
42 *
43 */
44
45 #include <machine/db_machdep.h>
46 #include <machine/setjmp.h>
47
48 #include <ddb/db_lex.h>
49 #include <ddb/db_break.h>
50 #include <ddb/db_command.h>
51
52
53
54 #define DB_MAX_COND 10 /* maximum conditions to be set */
55
56 int db_ncond_free = DB_MAX_COND; /* free condition */
57 struct db_cond {
58 int c_size; /* size of cond */
59 char c_cond_cmd[DB_LEX_LINE_SIZE]; /* cond & cmd */
60 } db_cond[DB_MAX_COND];
61
62 void
63 db_cond_free(bkpt)
64 db_thread_breakpoint_t bkpt;
65 {
66 if (bkpt->tb_cond > 0) {
67 db_cond[bkpt->tb_cond-1].c_size = 0;
68 db_ncond_free++;
69 bkpt->tb_cond = 0;
70 }
71 }
72
73 boolean_t
74 db_cond_check(bkpt)
75 db_thread_breakpoint_t bkpt;
76 {
77 register struct db_cond *cp;
78 db_expr_t value;
79 int t;
80 jmp_buf_t db_jmpbuf;
81 extern jmp_buf_t *db_recover;
82
83 if (bkpt->tb_cond <= 0) /* no condition */
84 return(TRUE);
85 db_dot = PC_REGS(DDB_REGS);
86 db_prev = db_dot;
87 db_next = db_dot;
88 if (_setjmp(db_recover = &db_jmpbuf)) {
89 /*
90 * in case of error, return true to enter interactive mode
91 */
92 return(TRUE);
93 }
94
95 /*
96 * switch input, and evalutate condition
97 */
98 cp = &db_cond[bkpt->tb_cond - 1];
99 db_switch_input(cp->c_cond_cmd, cp->c_size);
100 if (!db_expression(&value)) {
101 db_printf("error: condition evaluation error\n");
102 return(TRUE);
103 }
104 if (value == 0 || --(bkpt->tb_count) > 0)
105 return(FALSE);
106
107 /*
108 * execute a command list if exist
109 */
110 bkpt->tb_count = bkpt->tb_init_count;
111 if ((t = db_read_token()) != tEOL) {
112 db_unread_token(t);
113 return(db_exec_cmd_nest(0, 0));
114 }
115 return(TRUE);
116 }
117
118 void
119 db_cond_print(bkpt)
120 db_thread_breakpoint_t bkpt;
121 {
122 register char *p, *ep;
123 register struct db_cond *cp;
124
125 if (bkpt->tb_cond <= 0)
126 return;
127 cp = &db_cond[bkpt->tb_cond-1];
128 p = cp->c_cond_cmd;
129 ep = p + cp->c_size;
130 while (p < ep) {
131 if (*p == '\n' || *p == 0)
132 break;
133 db_putchar(*p++);
134 }
135 }
136
137 void
138 db_cond_cmd()
139 {
140 register c;
141 register struct db_cond *cp;
142 register char *p;
143 db_expr_t value;
144 db_thread_breakpoint_t bkpt;
145
146 if (db_read_token() != tHASH || db_read_token() != tNUMBER) {
147 db_printf("#<number> expected instead of \"%s\"\n", db_tok_string);
148 db_error(0);
149 return;
150 }
151 if ((bkpt = db_find_breakpoint_number(db_tok_number, 0)) == 0) {
152 db_printf("No such break point #%d\n", db_tok_number);
153 db_error(0);
154 return;
155 }
156 /*
157 * if the break point already has a condition, free it first
158 */
159 if (bkpt->tb_cond > 0) {
160 cp = &db_cond[bkpt->tb_cond - 1];
161 db_cond_free(bkpt);
162 } else {
163 if (db_ncond_free <= 0) {
164 db_error("Too many conditions\n");
165 return;
166 }
167 for (cp = db_cond; cp < &db_cond[DB_MAX_COND]; cp++)
168 if (cp->c_size == 0)
169 break;
170 if (cp >= &db_cond[DB_MAX_COND])
171 panic("bad db_cond_free");
172 }
173 for (c = db_read_char(); c == ' ' || c == '\t'; c = db_read_char());
174 for (p = cp->c_cond_cmd; c >= 0; c = db_read_char())
175 *p++ = c;
176 /*
177 * switch to saved data and call db_expression to check the condition.
178 * If no condition is supplied, db_expression will return false.
179 * In this case, clear previous condition of the break point.
180 * If condition is supplied, set the condition to the permanent area.
181 * Note: db_expression will not return here, if the condition
182 * expression is wrong.
183 */
184 db_switch_input(cp->c_cond_cmd, p - cp->c_cond_cmd);
185 if (!db_expression(&value)) {
186 /* since condition is already freed, do nothing */
187 db_flush_lex();
188 return;
189 }
190 db_flush_lex();
191 db_ncond_free--;
192 cp->c_size = p - cp->c_cond_cmd;
193 bkpt->tb_cond = (cp - db_cond) + 1;
194 }
Cache object: 02496795b0defe86d4ea247cb1e552ea
|