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