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