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