sync
[bitrig.git] / sys / ddb / db_lex.c
blob1bc9352f5f224ba8358bc3e1f0d4a1b9e1dc28ee
1 /* $OpenBSD: db_lex.c,v 1.9 2006/03/13 06:23:20 jsg Exp $ */
2 /* $NetBSD: db_lex.c,v 1.8 1996/02/05 01:57:05 christos Exp $ */
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.
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.
19 * Carnegie Mellon requests users of this software to return to
21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
22 * School of Computer Science
23 * Carnegie Mellon University
24 * Pittsburgh PA 15213-3890
26 * any improvements or extensions that they make and grant Carnegie Mellon
27 * the rights to redistribute these changes.
29 * Author: David B. Golub, Carnegie Mellon University
30 * Date: 7/90
34 * Lexical analyzer.
36 #include <sys/param.h>
37 #include <sys/proc.h>
39 #include <uvm/uvm_extern.h>
41 #include <machine/db_machdep.h>
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>
50 char db_line[120];
51 char * db_lp, *db_endlp;
53 db_expr_t db_tok_number;
54 char db_tok_string[TOK_STRING_SIZE];
56 int
57 db_read_line(void)
59 int i;
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);
69 void
70 db_flush_line(void)
72 db_lp = db_line;
73 db_endlp = db_line;
76 int db_look_char = 0;
78 int
79 db_read_char(void)
81 int c;
83 if (db_look_char != 0) {
84 c = db_look_char;
85 db_look_char = 0;
87 else if (db_lp >= db_endlp)
88 c = -1;
89 else
90 c = *db_lp++;
91 return (c);
94 void
95 db_unread_char(int c)
97 db_look_char = c;
100 int db_look_token = 0;
102 void
103 db_unread_token(int t)
105 db_look_token = t;
109 db_read_token(void)
111 int t;
113 if (db_look_token) {
114 t = db_look_token;
115 db_look_token = 0;
117 else
118 t = db_lex();
119 return (t);
122 void
123 db_flush_lex(void)
125 db_flush_line();
126 db_look_char = 0;
127 db_look_token = 0;
131 db_lex(void)
133 int c;
135 c = db_read_char();
136 while (c <= ' ' || c > '~') {
137 if (c == '\n' || c == -1)
138 return (tEOL);
139 c = db_read_char();
142 if (c >= '0' && c <= '9') {
143 /* number */
144 int r, digit = 0;
146 if (c > '0')
147 r = db_radix;
148 else {
149 c = db_read_char();
150 if (c == 'O' || c == 'o')
151 r = 8;
152 else if (c == 'T' || c == 't')
153 r = 10;
154 else if (c == 'X' || c == 'x')
155 r = 16;
156 else {
157 r = db_radix;
158 db_unread_char(c);
160 c = db_read_char();
162 db_tok_number = 0;
163 for (;;) {
164 if (c >= '0' && c <= ((r == 8) ? '7' : '9'))
165 digit = c - '0';
166 else if (r == 16 && ((c >= 'A' && c <= 'F') ||
167 (c >= 'a' && c <= 'f'))) {
168 if (c >= 'a')
169 digit = c - 'a' + 10;
170 else if (c >= 'A')
171 digit = c - 'A' + 10;
173 else
174 break;
175 db_tok_number = db_tok_number * r + digit;
176 c = db_read_char();
178 if ((c >= '0' && c <= '9') ||
179 (c >= 'A' && c <= 'Z') ||
180 (c >= 'a' && c <= 'z') ||
181 (c == '_'))
183 db_error("Bad character in number\n");
184 /*NOTREACHED*/
186 db_unread_char(c);
187 return (tNUMBER);
189 if ((c >= 'A' && c <= 'Z') ||
190 (c >= 'a' && c <= 'z') ||
191 c == '_' || c == '\\')
193 /* string */
194 char *cp;
196 cp = db_tok_string;
197 if (c == '\\') {
198 c = db_read_char();
199 if (c == '\n' || c == -1) {
200 db_error("Bad escape\n");
201 /*NOTREACHED*/
204 *cp++ = c;
205 while (1) {
206 c = db_read_char();
207 if ((c >= 'A' && c <= 'Z') ||
208 (c >= 'a' && c <= 'z') ||
209 (c >= '0' && c <= '9') ||
210 c == '_' || c == '\\' || c == ':')
212 if (c == '\\') {
213 c = db_read_char();
214 if (c == '\n' || c == -1) {
215 db_error("Bad escape\n");
216 /*NOTREACHED*/
219 *cp++ = c;
220 if (cp == db_tok_string+sizeof(db_tok_string)) {
221 db_error("String too long\n");
222 /*NOTREACHED*/
224 continue;
226 else {
227 *cp = '\0';
228 break;
231 db_unread_char(c);
232 return (tIDENT);
235 switch (c) {
236 case '+':
237 return (tPLUS);
238 case '-':
239 return (tMINUS);
240 case '.':
241 c = db_read_char();
242 if (c == '.')
243 return (tDOTDOT);
244 db_unread_char(c);
245 return (tDOT);
246 case '*':
247 return (tSTAR);
248 case '/':
249 return (tSLASH);
250 case '=':
251 return (tEQ);
252 case '%':
253 return (tPCT);
254 case '#':
255 return (tHASH);
256 case '(':
257 return (tLPAREN);
258 case ')':
259 return (tRPAREN);
260 case ',':
261 return (tCOMMA);
262 case '"':
263 return (tDITTO);
264 case '$':
265 return (tDOLLAR);
266 case '!':
267 return (tEXCL);
268 case '<':
269 c = db_read_char();
270 if (c == '<')
271 return (tSHIFT_L);
272 db_unread_char(c);
273 break;
274 case '>':
275 c = db_read_char();
276 if (c == '>')
277 return (tSHIFT_R);
278 db_unread_char(c);
279 break;
280 case -1:
281 return (tEOF);
283 db_printf("Bad character\n");
284 db_flush_lex();
285 return (tEOF);