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