xref: /netbsd-src/sys/ddb/db_lex.c (revision ae9172d6cd9432a6a1a56760d86b32c57a66c39c)
1 /*	$NetBSD: db_lex.c,v 1.7 1994/10/09 08:56:25 mycroft 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 <ddb/db_lex.h>
38 
39 char	db_line[120];
40 char *	db_lp, *db_endlp;
41 
42 int
43 db_read_line()
44 {
45 	int	i;
46 
47 	i = db_readline(db_line, sizeof(db_line));
48 	if (i == 0)
49 	    return (0);	/* EOI */
50 	db_lp = db_line;
51 	db_endlp = db_lp + i;
52 	return (i);
53 }
54 
55 void
56 db_flush_line()
57 {
58 	db_lp = db_line;
59 	db_endlp = db_line;
60 }
61 
62 int	db_look_char = 0;
63 
64 int
65 db_read_char()
66 {
67 	int	c;
68 
69 	if (db_look_char != 0) {
70 	    c = db_look_char;
71 	    db_look_char = 0;
72 	}
73 	else if (db_lp >= db_endlp)
74 	    c = -1;
75 	else
76 	    c = *db_lp++;
77 	return (c);
78 }
79 
80 void
81 db_unread_char(c)
82 	int c;
83 {
84 	db_look_char = c;
85 }
86 
87 int	db_look_token = 0;
88 
89 void
90 db_unread_token(t)
91 	int	t;
92 {
93 	db_look_token = t;
94 }
95 
96 int
97 db_read_token()
98 {
99 	int	t;
100 
101 	if (db_look_token) {
102 	    t = db_look_token;
103 	    db_look_token = 0;
104 	}
105 	else
106 	    t = db_lex();
107 	return (t);
108 }
109 
110 int	db_radix = 16;
111 
112 void
113 db_flush_lex()
114 {
115 	db_flush_line();
116 	db_look_char = 0;
117 	db_look_token = 0;
118 }
119 
120 int
121 db_lex()
122 {
123 	int	c;
124 
125 	c = db_read_char();
126 	while (c <= ' ' || c > '~') {
127 	    if (c == '\n' || c == -1)
128 		return (tEOL);
129 	    c = db_read_char();
130 	}
131 
132 	if (c >= '0' && c <= '9') {
133 	    /* number */
134 	    int	r, digit;
135 
136 	    if (c > '0')
137 		r = db_radix;
138 	    else {
139 		c = db_read_char();
140 		if (c == 'O' || c == 'o')
141 		    r = 8;
142 		else if (c == 'T' || c == 't')
143 		    r = 10;
144 		else if (c == 'X' || c == 'x')
145 		    r = 16;
146 		else {
147 		    r = db_radix;
148 		    db_unread_char(c);
149 		}
150 		c = db_read_char();
151 	    }
152 	    db_tok_number = 0;
153 	    for (;;) {
154 		if (c >= '0' && c <= ((r == 8) ? '7' : '9'))
155 		    digit = c - '0';
156 		else if (r == 16 && ((c >= 'A' && c <= 'F') ||
157 				     (c >= 'a' && c <= 'f'))) {
158 		    if (c >= 'a')
159 			digit = c - 'a' + 10;
160 		    else if (c >= 'A')
161 			digit = c - 'A' + 10;
162 		}
163 		else
164 		    break;
165 		db_tok_number = db_tok_number * r + digit;
166 		c = db_read_char();
167 	    }
168 	    if ((c >= '0' && c <= '9') ||
169 		(c >= 'A' && c <= 'Z') ||
170 		(c >= 'a' && c <= 'z') ||
171 		(c == '_'))
172 	    {
173 		db_error("Bad character in number\n");
174 		/*NOTREACHED*/
175 	    }
176 	    db_unread_char(c);
177 	    return (tNUMBER);
178 	}
179 	if ((c >= 'A' && c <= 'Z') ||
180 	    (c >= 'a' && c <= 'z') ||
181 	    c == '_' || c == '\\')
182 	{
183 	    /* string */
184 	    char *cp;
185 
186 	    cp = db_tok_string;
187 	    if (c == '\\') {
188 		c = db_read_char();
189 		if (c == '\n' || c == -1) {
190 		    db_error("Bad escape\n");
191 		    /*NOTREACHED*/
192 		}
193 	    }
194 	    *cp++ = c;
195 	    while (1) {
196 		c = db_read_char();
197 		if ((c >= 'A' && c <= 'Z') ||
198 		    (c >= 'a' && c <= 'z') ||
199 		    (c >= '0' && c <= '9') ||
200 		    c == '_' || c == '\\' || c == ':')
201 		{
202 		    if (c == '\\') {
203 			c = db_read_char();
204 			if (c == '\n' || c == -1) {
205 			    db_error("Bad escape\n");
206 			    /*NOTREACHED*/
207 			}
208 		    }
209 		    *cp++ = c;
210 		    if (cp == db_tok_string+sizeof(db_tok_string)) {
211 			db_error("String too long\n");
212 			/*NOTREACHED*/
213 		    }
214 		    continue;
215 		}
216 		else {
217 		    *cp = '\0';
218 		    break;
219 		}
220 	    }
221 	    db_unread_char(c);
222 	    return (tIDENT);
223 	}
224 
225 	switch (c) {
226 	    case '+':
227 		return (tPLUS);
228 	    case '-':
229 		return (tMINUS);
230 	    case '.':
231 		c = db_read_char();
232 		if (c == '.')
233 		    return (tDOTDOT);
234 		db_unread_char(c);
235 		return (tDOT);
236 	    case '*':
237 		return (tSTAR);
238 	    case '/':
239 		return (tSLASH);
240 	    case '=':
241 		return (tEQ);
242 	    case '%':
243 		return (tPCT);
244 	    case '#':
245 		return (tHASH);
246 	    case '(':
247 		return (tLPAREN);
248 	    case ')':
249 		return (tRPAREN);
250 	    case ',':
251 		return (tCOMMA);
252 	    case '"':
253 		return (tDITTO);
254 	    case '$':
255 		return (tDOLLAR);
256 	    case '!':
257 		return (tEXCL);
258 	    case '<':
259 		c = db_read_char();
260 		if (c == '<')
261 		    return (tSHIFT_L);
262 		db_unread_char(c);
263 		break;
264 	    case '>':
265 		c = db_read_char();
266 		if (c == '>')
267 		    return (tSHIFT_R);
268 		db_unread_char(c);
269 		break;
270 	    case -1:
271 		return (tEOF);
272 	}
273 	db_printf("Bad character\n");
274 	db_flush_lex();
275 	return (tEOF);
276 }
277