db_lex.c revision 1.8 1 /* $NetBSD: db_lex.c,v 1.8 1996/02/05 01:57:05 christos 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
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 void
119 db_flush_lex()
120 {
121 db_flush_line();
122 db_look_char = 0;
123 db_look_token = 0;
124 }
125
126 int
127 db_lex()
128 {
129 int c;
130
131 c = db_read_char();
132 while (c <= ' ' || c > '~') {
133 if (c == '\n' || c == -1)
134 return (tEOL);
135 c = db_read_char();
136 }
137
138 if (c >= '0' && c <= '9') {
139 /* number */
140 int r, digit = 0;
141
142 if (c > '0')
143 r = db_radix;
144 else {
145 c = db_read_char();
146 if (c == 'O' || c == 'o')
147 r = 8;
148 else if (c == 'T' || c == 't')
149 r = 10;
150 else if (c == 'X' || c == 'x')
151 r = 16;
152 else {
153 r = db_radix;
154 db_unread_char(c);
155 }
156 c = db_read_char();
157 }
158 db_tok_number = 0;
159 for (;;) {
160 if (c >= '0' && c <= ((r == 8) ? '7' : '9'))
161 digit = c - '0';
162 else if (r == 16 && ((c >= 'A' && c <= 'F') ||
163 (c >= 'a' && c <= 'f'))) {
164 if (c >= 'a')
165 digit = c - 'a' + 10;
166 else if (c >= 'A')
167 digit = c - 'A' + 10;
168 }
169 else
170 break;
171 db_tok_number = db_tok_number * r + digit;
172 c = db_read_char();
173 }
174 if ((c >= '0' && c <= '9') ||
175 (c >= 'A' && c <= 'Z') ||
176 (c >= 'a' && c <= 'z') ||
177 (c == '_'))
178 {
179 db_error("Bad character in number\n");
180 /*NOTREACHED*/
181 }
182 db_unread_char(c);
183 return (tNUMBER);
184 }
185 if ((c >= 'A' && c <= 'Z') ||
186 (c >= 'a' && c <= 'z') ||
187 c == '_' || c == '\\')
188 {
189 /* string */
190 char *cp;
191
192 cp = db_tok_string;
193 if (c == '\\') {
194 c = db_read_char();
195 if (c == '\n' || c == -1) {
196 db_error("Bad escape\n");
197 /*NOTREACHED*/
198 }
199 }
200 *cp++ = c;
201 while (1) {
202 c = db_read_char();
203 if ((c >= 'A' && c <= 'Z') ||
204 (c >= 'a' && c <= 'z') ||
205 (c >= '0' && c <= '9') ||
206 c == '_' || c == '\\' || c == ':')
207 {
208 if (c == '\\') {
209 c = db_read_char();
210 if (c == '\n' || c == -1) {
211 db_error("Bad escape\n");
212 /*NOTREACHED*/
213 }
214 }
215 *cp++ = c;
216 if (cp == db_tok_string+sizeof(db_tok_string)) {
217 db_error("String too long\n");
218 /*NOTREACHED*/
219 }
220 continue;
221 }
222 else {
223 *cp = '\0';
224 break;
225 }
226 }
227 db_unread_char(c);
228 return (tIDENT);
229 }
230
231 switch (c) {
232 case '+':
233 return (tPLUS);
234 case '-':
235 return (tMINUS);
236 case '.':
237 c = db_read_char();
238 if (c == '.')
239 return (tDOTDOT);
240 db_unread_char(c);
241 return (tDOT);
242 case '*':
243 return (tSTAR);
244 case '/':
245 return (tSLASH);
246 case '=':
247 return (tEQ);
248 case '%':
249 return (tPCT);
250 case '#':
251 return (tHASH);
252 case '(':
253 return (tLPAREN);
254 case ')':
255 return (tRPAREN);
256 case ',':
257 return (tCOMMA);
258 case '"':
259 return (tDITTO);
260 case '$':
261 return (tDOLLAR);
262 case '!':
263 return (tEXCL);
264 case '<':
265 c = db_read_char();
266 if (c == '<')
267 return (tSHIFT_L);
268 db_unread_char(c);
269 break;
270 case '>':
271 c = db_read_char();
272 if (c == '>')
273 return (tSHIFT_R);
274 db_unread_char(c);
275 break;
276 case -1:
277 return (tEOF);
278 }
279 db_printf("Bad character\n");
280 db_flush_lex();
281 return (tEOF);
282 }
283