db_lex.c revision 1.4 1 /* $NetBSD: db_lex.c,v 1.4 1994/06/29 06:31:10 cgd 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 <ddb/db_lex.h>
36
37 char db_line[120];
38 char * db_lp, *db_endlp;
39
40 int
41 db_read_line()
42 {
43 int i;
44
45 i = db_readline(db_line, sizeof(db_line));
46 if (i == 0)
47 return (0); /* EOI */
48 db_lp = db_line;
49 db_endlp = db_lp + i;
50 return (i);
51 }
52
53 void
54 db_flush_line()
55 {
56 db_lp = db_line;
57 db_endlp = db_line;
58 }
59
60 int db_look_char = 0;
61
62 int
63 db_read_char()
64 {
65 int c;
66
67 if (db_look_char != 0) {
68 c = db_look_char;
69 db_look_char = 0;
70 }
71 else if (db_lp >= db_endlp)
72 c = -1;
73 else
74 c = *db_lp++;
75 return (c);
76 }
77
78 void
79 db_unread_char(c)
80 {
81 db_look_char = c;
82 }
83
84 int db_look_token = 0;
85
86 void
87 db_unread_token(t)
88 int t;
89 {
90 db_look_token = t;
91 }
92
93 int
94 db_read_token()
95 {
96 int t;
97
98 if (db_look_token) {
99 t = db_look_token;
100 db_look_token = 0;
101 }
102 else
103 t = db_lex();
104 return (t);
105 }
106
107 int db_tok_number;
108 char db_tok_string[TOK_STRING_SIZE];
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 db_flush_lex();
175 return (tEOF);
176 }
177 db_unread_char(c);
178 return (tNUMBER);
179 }
180 if ((c >= 'A' && c <= 'Z') ||
181 (c >= 'a' && c <= 'z') ||
182 c == '_' || c == '\\')
183 {
184 /* string */
185 char *cp;
186
187 cp = db_tok_string;
188 if (c == '\\') {
189 c = db_read_char();
190 if (c == '\n' || c == -1)
191 db_error("Bad escape\n");
192 }
193 *cp++ = c;
194 while (1) {
195 c = db_read_char();
196 if ((c >= 'A' && c <= 'Z') ||
197 (c >= 'a' && c <= 'z') ||
198 (c >= '0' && c <= '9') ||
199 c == '_' || c == '\\' || c == ':')
200 {
201 if (c == '\\') {
202 c = db_read_char();
203 if (c == '\n' || c == -1)
204 db_error("Bad escape\n");
205 }
206 *cp++ = c;
207 if (cp == db_tok_string+sizeof(db_tok_string)) {
208 db_error("String too long\n");
209 db_flush_lex();
210 return (tEOF);
211 }
212 continue;
213 }
214 else {
215 *cp = '\0';
216 break;
217 }
218 }
219 db_unread_char(c);
220 return (tIDENT);
221 }
222
223 switch (c) {
224 case '+':
225 return (tPLUS);
226 case '-':
227 return (tMINUS);
228 case '.':
229 c = db_read_char();
230 if (c == '.')
231 return (tDOTDOT);
232 db_unread_char(c);
233 return (tDOT);
234 case '*':
235 return (tSTAR);
236 case '/':
237 return (tSLASH);
238 case '=':
239 return (tEQ);
240 case '%':
241 return (tPCT);
242 case '#':
243 return (tHASH);
244 case '(':
245 return (tLPAREN);
246 case ')':
247 return (tRPAREN);
248 case ',':
249 return (tCOMMA);
250 case '"':
251 return (tDITTO);
252 case '$':
253 return (tDOLLAR);
254 case '!':
255 return (tEXCL);
256 case '<':
257 c = db_read_char();
258 if (c == '<')
259 return (tSHIFT_L);
260 db_unread_char(c);
261 break;
262 case '>':
263 c = db_read_char();
264 if (c == '>')
265 return (tSHIFT_R);
266 db_unread_char(c);
267 break;
268 case -1:
269 return (tEOF);
270 }
271 db_printf("Bad character\n");
272 db_flush_lex();
273 return (tEOF);
274 }
275