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