xref: /netbsd-src/sys/ddb/db_lex.c (revision 76dfffe33547c37f8bdd446e3e4ab0f3c16cea4b)
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@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