FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_lex.c
1 /* $NetBSD: db_lex.c,v 1.18 2003/05/17 09:58:03 scw Exp $ */
2
3 /*
4 * Mach Operating System
5 * Copyright (c) 1991,1990 Carnegie Mellon University
6 * All Rights Reserved.
7 *
8 * Permission to use, copy, modify and distribute this software and its
9 * documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
13 *
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
27 *
28 * Author: David B. Golub, Carnegie Mellon University
29 * Date: 7/90
30 */
31
32 /*
33 * Lexical analyzer.
34 */
35
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: db_lex.c,v 1.18 2003/05/17 09:58:03 scw Exp $");
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41
42 #include <machine/db_machdep.h>
43
44 #include <ddb/db_lex.h>
45 #include <ddb/db_output.h>
46 #include <ddb/db_command.h>
47 #include <ddb/db_sym.h>
48 #include <ddb/db_extern.h>
49 #include <ddb/db_interface.h>
50
51 db_expr_t db_tok_number;
52 char db_tok_string[TOK_STRING_SIZE];
53
54 static char db_line[120];
55 static char *db_lp, *db_endlp;
56
57 static int db_look_char = 0;
58 static int db_look_token = 0;
59
60 static void db_flush_line(void);
61 static int db_read_char(void);
62 static void db_unread_char(int);
63 static int db_lex(void);
64
65 int
66 db_read_line(void)
67 {
68 int i;
69
70 i = db_readline(db_line, sizeof(db_line));
71 if (i == 0)
72 return (0); /* EOI */
73 db_lp = db_line;
74 db_endlp = db_lp + i;
75 return (i);
76 }
77
78 static void
79 db_flush_line(void)
80 {
81
82 db_lp = db_line;
83 db_endlp = db_line;
84 }
85
86 static int
87 db_read_char(void)
88 {
89 int c;
90
91 if (db_look_char != 0) {
92 c = db_look_char;
93 db_look_char = 0;
94 }
95 else if (db_lp >= db_endlp)
96 c = -1;
97 else
98 c = *db_lp++;
99 return (c);
100 }
101
102 static void
103 db_unread_char(int c)
104 {
105
106 db_look_char = c;
107 }
108
109 void
110 db_unread_token(int t)
111 {
112
113 db_look_token = t;
114 }
115
116 int
117 db_read_token(void)
118 {
119 int t;
120
121 if (db_look_token) {
122 t = db_look_token;
123 db_look_token = 0;
124 }
125 else
126 t = db_lex();
127 return (t);
128 }
129
130 int db_radix = 16;
131
132 /*
133 * Convert the number to a string in the current radix.
134 * This replaces the non-standard %n printf() format.
135 */
136
137 char *
138 db_num_to_str(db_expr_t val)
139 {
140
141 /*
142 * 2 chars for "0x", 1 for a sign ("-")
143 * up to 21 chars for a 64-bit number:
144 * % echo 2^64 | bc | wc -c
145 * 21
146 * and 1 char for a terminal NUL
147 * 2+1+21+1 => 25
148 */
149 static char buf[25];
150
151 if (db_radix == 16)
152 snprintf(buf, sizeof(buf), DB_EXPR_T_IS_QUAD ? "%#qx" : "%#lx",
153 val);
154 else if (db_radix == 8)
155 snprintf(buf, sizeof(buf), DB_EXPR_T_IS_QUAD ? "%#qo" : "%#lo",
156 val);
157 else
158 snprintf(buf, sizeof(buf), DB_EXPR_T_IS_QUAD ? "%qu" : "%lu",
159 val);
160
161 return (buf);
162 }
163
164 void
165 db_flush_lex(void)
166 {
167
168 db_flush_line();
169 db_look_char = 0;
170 db_look_token = 0;
171 }
172
173 static int
174 db_lex(void)
175 {
176 int c;
177
178 c = db_read_char();
179 while (c <= ' ' || c > '~') {
180 if (c == '\n' || c == -1)
181 return (tEOL);
182 c = db_read_char();
183 }
184
185 if (c >= '' && c <= '9') {
186 /* number */
187 db_expr_t r, digit = 0;
188
189 if (c > '')
190 r = db_radix;
191 else {
192 c = db_read_char();
193 if (c == 'O' || c == 'o')
194 r = 8;
195 else if (c == 'T' || c == 't')
196 r = 10;
197 else if (c == 'X' || c == 'x')
198 r = 16;
199 else {
200 r = db_radix;
201 db_unread_char(c);
202 }
203 c = db_read_char();
204 }
205 db_tok_number = 0;
206 for (;;) {
207 if (c >= '' && c <= ((r == 8) ? '7' : '9'))
208 digit = c - '';
209 else if (r == 16 && ((c >= 'A' && c <= 'F') ||
210 (c >= 'a' && c <= 'f'))) {
211 if (c >= 'a')
212 digit = c - 'a' + 10;
213 else if (c >= 'A')
214 digit = c - 'A' + 10;
215 }
216 else
217 break;
218 db_tok_number = db_tok_number * r + digit;
219 c = db_read_char();
220 }
221 if ((c >= '' && c <= '9') ||
222 (c >= 'A' && c <= 'Z') ||
223 (c >= 'a' && c <= 'z') ||
224 (c == '_')) {
225 db_error("Bad character in number\n");
226 /*NOTREACHED*/
227 }
228 db_unread_char(c);
229 return (tNUMBER);
230 }
231 if ((c >= 'A' && c <= 'Z') ||
232 (c >= 'a' && c <= 'z') ||
233 c == '_' || c == '\\') {
234 /* string */
235 char *cp;
236
237 cp = db_tok_string;
238 if (c == '\\') {
239 c = db_read_char();
240 if (c == '\n' || c == -1) {
241 db_error("Bad escape\n");
242 /*NOTREACHED*/
243 }
244 }
245 *cp++ = c;
246 while (1) {
247 c = db_read_char();
248 if ((c >= 'A' && c <= 'Z') ||
249 (c >= 'a' && c <= 'z') ||
250 (c >= '' && c <= '9') ||
251 c == '_' || c == '\\' || c == ':') {
252 if (c == '\\') {
253 c = db_read_char();
254 if (c == '\n' || c == -1) {
255 db_error("Bad escape\n");
256 /*NOTREACHED*/
257 }
258 }
259 *cp++ = c;
260 if (cp == db_tok_string+sizeof(db_tok_string)) {
261 db_error("String too long\n");
262 /*NOTREACHED*/
263 }
264 continue;
265 } else {
266 *cp = '\0';
267 break;
268 }
269 }
270 db_unread_char(c);
271 return (tIDENT);
272 }
273
274 switch (c) {
275 case '+':
276 return (tPLUS);
277 case '-':
278 return (tMINUS);
279 case '.':
280 c = db_read_char();
281 if (c == '.')
282 return (tDOTDOT);
283 db_unread_char(c);
284 return (tDOT);
285 case '*':
286 return (tSTAR);
287 case '/':
288 return (tSLASH);
289 case '=':
290 return (tEQ);
291 case '%':
292 return (tPCT);
293 case '#':
294 return (tHASH);
295 case '(':
296 return (tLPAREN);
297 case ')':
298 return (tRPAREN);
299 case ',':
300 return (tCOMMA);
301 case '"':
302 return (tDITTO);
303 case '$':
304 return (tDOLLAR);
305 case '!':
306 return (tEXCL);
307 case '<':
308 c = db_read_char();
309 if (c == '<')
310 return (tSHIFT_L);
311 db_unread_char(c);
312 break;
313 case '>':
314 c = db_read_char();
315 if (c == '>')
316 return (tSHIFT_R);
317 db_unread_char(c);
318 break;
319 case -1:
320 return (tEOF);
321 }
322 db_printf("Bad character\n");
323 db_flush_lex();
324 return (tEOF);
325 }
Cache object: 769330452670691974e76dd66ecaba24
|