FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_lex.c
1 /* $NetBSD: db_lex.c,v 1.20 2005/11/27 13:05:28 yamt 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.20 2005/11/27 13:05:28 yamt 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[DB_LINE_MAXLEN];
55 static const char *db_lp;
56 static const char *db_endlp;
57
58 static int db_look_char = 0;
59 static int db_look_token = 0;
60
61 static void db_flush_line(void);
62 static int db_read_char(void);
63 static void db_unread_char(int);
64 static int db_lex(void);
65
66 int
67 db_read_line(void)
68 {
69 int i;
70
71 i = db_readline(db_line, sizeof(db_line));
72 if (i == 0)
73 return (0); /* EOI */
74 db_set_line(db_line, db_line + i);
75 return (i);
76 }
77
78 void
79 db_set_line(const char *sp, const char *ep)
80 {
81
82 db_lp = sp;
83 db_endlp = ep;
84 }
85
86 static void
87 db_flush_line(void)
88 {
89
90 db_lp = db_line;
91 db_endlp = db_line;
92 }
93
94 static int
95 db_read_char(void)
96 {
97 int c;
98
99 if (db_look_char != 0) {
100 c = db_look_char;
101 db_look_char = 0;
102 }
103 else if (db_lp >= db_endlp)
104 c = -1;
105 else
106 c = *db_lp++;
107 return (c);
108 }
109
110 static void
111 db_unread_char(int c)
112 {
113
114 db_look_char = c;
115 }
116
117 void
118 db_unread_token(int t)
119 {
120
121 db_look_token = t;
122 }
123
124 int
125 db_read_token(void)
126 {
127 int t;
128
129 if (db_look_token) {
130 t = db_look_token;
131 db_look_token = 0;
132 }
133 else
134 t = db_lex();
135 return (t);
136 }
137
138 int db_radix = 16;
139
140 /*
141 * Convert the number to a string in the current radix.
142 * This replaces the non-standard %n printf() format.
143 */
144
145 char *
146 db_num_to_str(db_expr_t val)
147 {
148
149 /*
150 * 2 chars for "0x", 1 for a sign ("-")
151 * up to 21 chars for a 64-bit number:
152 * % echo 2^64 | bc | wc -c
153 * 21
154 * and 1 char for a terminal NUL
155 * 2+1+21+1 => 25
156 */
157 static char buf[25];
158
159 if (db_radix == 16)
160 snprintf(buf, sizeof(buf), DB_EXPR_T_IS_QUAD ? "%#qx" : "%#lx",
161 val);
162 else if (db_radix == 8)
163 snprintf(buf, sizeof(buf), DB_EXPR_T_IS_QUAD ? "%#qo" : "%#lo",
164 val);
165 else
166 snprintf(buf, sizeof(buf), DB_EXPR_T_IS_QUAD ? "%qu" : "%lu",
167 val);
168
169 return (buf);
170 }
171
172 void
173 db_flush_lex(void)
174 {
175
176 db_flush_line();
177 db_look_char = 0;
178 db_look_token = 0;
179 }
180
181 static int
182 db_lex(void)
183 {
184 int c;
185
186 c = db_read_char();
187 while (c <= ' ' || c > '~') {
188 if (c == '\n' || c == -1)
189 return (tEOL);
190 c = db_read_char();
191 }
192
193 if (c >= '' && c <= '9') {
194 /* number */
195 db_expr_t r, digit = 0;
196
197 if (c > '')
198 r = db_radix;
199 else {
200 c = db_read_char();
201 if (c == 'O' || c == 'o')
202 r = 8;
203 else if (c == 'T' || c == 't')
204 r = 10;
205 else if (c == 'X' || c == 'x')
206 r = 16;
207 else {
208 r = db_radix;
209 db_unread_char(c);
210 }
211 c = db_read_char();
212 }
213 db_tok_number = 0;
214 for (;;) {
215 if (c >= '' && c <= ((r == 8) ? '7' : '9'))
216 digit = c - '';
217 else if (r == 16 && ((c >= 'A' && c <= 'F') ||
218 (c >= 'a' && c <= 'f'))) {
219 if (c >= 'a')
220 digit = c - 'a' + 10;
221 else if (c >= 'A')
222 digit = c - 'A' + 10;
223 }
224 else
225 break;
226 db_tok_number = db_tok_number * r + digit;
227 c = db_read_char();
228 }
229 if ((c >= '' && c <= '9') ||
230 (c >= 'A' && c <= 'Z') ||
231 (c >= 'a' && c <= 'z') ||
232 (c == '_')) {
233 db_error("Bad character in number\n");
234 /*NOTREACHED*/
235 }
236 db_unread_char(c);
237 return (tNUMBER);
238 }
239 if ((c >= 'A' && c <= 'Z') ||
240 (c >= 'a' && c <= 'z') ||
241 c == '_' || c == '\\') {
242 /* string */
243 char *cp;
244
245 cp = db_tok_string;
246 if (c == '\\') {
247 c = db_read_char();
248 if (c == '\n' || c == -1) {
249 db_error("Bad escape\n");
250 /*NOTREACHED*/
251 }
252 }
253 *cp++ = c;
254 while (1) {
255 c = db_read_char();
256 if ((c >= 'A' && c <= 'Z') ||
257 (c >= 'a' && c <= 'z') ||
258 (c >= '' && c <= '9') ||
259 c == '_' || c == '\\' || c == ':') {
260 if (c == '\\') {
261 c = db_read_char();
262 if (c == '\n' || c == -1) {
263 db_error("Bad escape\n");
264 /*NOTREACHED*/
265 }
266 }
267 *cp++ = c;
268 if (cp == db_tok_string+sizeof(db_tok_string)) {
269 db_error("String too long\n");
270 /*NOTREACHED*/
271 }
272 continue;
273 } else {
274 *cp = '\0';
275 break;
276 }
277 }
278 db_unread_char(c);
279 return (tIDENT);
280 }
281
282 switch (c) {
283 case '+':
284 return (tPLUS);
285 case '-':
286 return (tMINUS);
287 case '.':
288 c = db_read_char();
289 if (c == '.')
290 return (tDOTDOT);
291 db_unread_char(c);
292 return (tDOT);
293 case '*':
294 return (tSTAR);
295 case '/':
296 return (tSLASH);
297 case '=':
298 return (tEQ);
299 case '%':
300 return (tPCT);
301 case '#':
302 return (tHASH);
303 case '(':
304 return (tLPAREN);
305 case ')':
306 return (tRPAREN);
307 case ',':
308 return (tCOMMA);
309 case '"':
310 return (tDITTO);
311 case '$':
312 return (tDOLLAR);
313 case '!':
314 return (tEXCL);
315 case '<':
316 c = db_read_char();
317 if (c == '<')
318 return (tSHIFT_L);
319 db_unread_char(c);
320 break;
321 case '>':
322 c = db_read_char();
323 if (c == '>')
324 return (tSHIFT_R);
325 db_unread_char(c);
326 break;
327 case -1:
328 return (tEOF);
329 }
330 db_printf("Bad character\n");
331 db_flush_lex();
332 return (tEOF);
333 }
Cache object: 8ff716d370861a4589c5052005376588
|