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