Add a small set of logical operators to DDB command language.
[freebsd-src.git] / sys / ddb / db_lex.c
blob4fdfa317c6e4a7aa89669273b950cdd83ccdefbe
1 /*-
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
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.
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.
16 * Carnegie Mellon requests users of this software to return to
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
23 * any improvements or extensions that they make and grant Carnegie the
24 * rights to redistribute these changes.
27 * Author: David B. Golub, Carnegie Mellon University
28 * Date: 7/90
31 * Lexical analyzer.
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
37 #include <sys/param.h>
38 #include <sys/libkern.h>
40 #include <ddb/ddb.h>
41 #include <ddb/db_lex.h>
43 static char db_line[DB_MAXLINE];
44 static char * db_lp, *db_endlp;
46 static int db_lex(void);
47 static void db_flush_line(void);
48 static int db_read_char(void);
49 static void db_unread_char(int);
51 int
52 db_read_line(void)
54 int i;
56 i = db_readline(db_line, sizeof(db_line));
57 if (i == 0)
58 return (0); /* EOI */
59 db_lp = db_line;
60 db_endlp = db_lp + i;
61 return (i);
65 * Simulate a line of input into DDB.
67 void
68 db_inject_line(const char *command)
71 strlcpy(db_line, command, sizeof(db_line));
72 db_lp = db_line;
73 db_endlp = db_lp + strlen(command);
77 * In rare cases, we may want to pull the remainder of the line input
78 * verbatim, rather than lexing it. For example, when assigning literal
79 * values associated with scripts. In that case, return a static pointer to
80 * the current location in the input buffer. The caller must be aware that
81 * the contents are not stable if other lex/input calls are made.
83 char *
84 db_get_line(void)
87 return (db_lp);
90 static void
91 db_flush_line()
93 db_lp = db_line;
94 db_endlp = db_line;
97 static int db_look_char = 0;
99 static int
100 db_read_char(void)
102 int c;
104 if (db_look_char != 0) {
105 c = db_look_char;
106 db_look_char = 0;
108 else if (db_lp >= db_endlp)
109 c = -1;
110 else
111 c = *db_lp++;
112 return (c);
115 static void
116 db_unread_char(c)
117 int c;
119 db_look_char = c;
122 static int db_look_token = 0;
124 void
125 db_unread_token(t)
126 int t;
128 db_look_token = t;
132 db_read_token()
134 int t;
136 if (db_look_token) {
137 t = db_look_token;
138 db_look_token = 0;
140 else
141 t = db_lex();
142 return (t);
145 db_expr_t db_tok_number;
146 char db_tok_string[TOK_STRING_SIZE];
148 db_expr_t db_radix = 16;
150 void
151 db_flush_lex(void)
153 db_flush_line();
154 db_look_char = 0;
155 db_look_token = 0;
158 static int
159 db_lex(void)
161 int c;
163 c = db_read_char();
164 while (c <= ' ' || c > '~') {
165 if (c == '\n' || c == -1)
166 return (tEOL);
167 c = db_read_char();
170 if (c >= '0' && c <= '9') {
171 /* number */
172 int r, digit = 0;
174 if (c > '0')
175 r = db_radix;
176 else {
177 c = db_read_char();
178 if (c == 'O' || c == 'o')
179 r = 8;
180 else if (c == 'T' || c == 't')
181 r = 10;
182 else if (c == 'X' || c == 'x')
183 r = 16;
184 else {
185 r = db_radix;
186 db_unread_char(c);
188 c = db_read_char();
190 db_tok_number = 0;
191 for (;;) {
192 if (c >= '0' && c <= ((r == 8) ? '7' : '9'))
193 digit = c - '0';
194 else if (r == 16 && ((c >= 'A' && c <= 'F') ||
195 (c >= 'a' && c <= 'f'))) {
196 if (c >= 'a')
197 digit = c - 'a' + 10;
198 else if (c >= 'A')
199 digit = c - 'A' + 10;
201 else
202 break;
203 db_tok_number = db_tok_number * r + digit;
204 c = db_read_char();
206 if ((c >= '0' && c <= '9') ||
207 (c >= 'A' && c <= 'Z') ||
208 (c >= 'a' && c <= 'z') ||
209 (c == '_'))
211 db_error("Bad character in number\n");
212 db_flush_lex();
213 return (tEOF);
215 db_unread_char(c);
216 return (tNUMBER);
218 if ((c >= 'A' && c <= 'Z') ||
219 (c >= 'a' && c <= 'z') ||
220 c == '_' || c == '\\')
222 /* string */
223 char *cp;
225 cp = db_tok_string;
226 if (c == '\\') {
227 c = db_read_char();
228 if (c == '\n' || c == -1)
229 db_error("Bad escape\n");
231 *cp++ = c;
232 while (1) {
233 c = db_read_char();
234 if ((c >= 'A' && c <= 'Z') ||
235 (c >= 'a' && c <= 'z') ||
236 (c >= '0' && c <= '9') ||
237 c == '_' || c == '\\' || c == ':' || c == '.')
239 if (c == '\\') {
240 c = db_read_char();
241 if (c == '\n' || c == -1)
242 db_error("Bad escape\n");
244 *cp++ = c;
245 if (cp == db_tok_string+sizeof(db_tok_string)) {
246 db_error("String too long\n");
247 db_flush_lex();
248 return (tEOF);
250 continue;
252 else {
253 *cp = '\0';
254 break;
257 db_unread_char(c);
258 return (tIDENT);
261 switch (c) {
262 case '+':
263 return (tPLUS);
264 case '-':
265 return (tMINUS);
266 case '.':
267 c = db_read_char();
268 if (c == '.')
269 return (tDOTDOT);
270 db_unread_char(c);
271 return (tDOT);
272 case '*':
273 return (tSTAR);
274 case '/':
275 return (tSLASH);
276 case '=':
277 c = db_read_char();
278 if (c == '=')
279 return (tLOG_EQ);
280 db_unread_char(c);
281 return (tEQ);
282 case '%':
283 return (tPCT);
284 case '#':
285 return (tHASH);
286 case '(':
287 return (tLPAREN);
288 case ')':
289 return (tRPAREN);
290 case ',':
291 return (tCOMMA);
292 case '"':
293 return (tDITTO);
294 case '$':
295 return (tDOLLAR);
296 case '!':
297 c = db_read_char();
298 if (c == '='){
299 return (tLOG_NOT_EQ);
301 db_unread_char(c);
302 return (tEXCL);
303 case ';':
304 return (tSEMI);
305 case '&':
306 c = db_read_char();
307 if (c == '&')
308 return (tLOG_AND);
309 db_unread_char(c);
310 return (tBIT_AND);
311 case '|':
312 c = db_read_char();
313 if (c == '|')
314 return (tLOG_OR);
315 db_unread_char(c);
316 return (tBIT_OR);
317 case '<':
318 c = db_read_char();
319 if (c == '<')
320 return (tSHIFT_L);
321 if (c == '=')
322 return (tLESS_EQ);
323 db_unread_char(c);
324 return (tLESS);
325 case '>':
326 c = db_read_char();
327 if (c == '>')
328 return (tSHIFT_R);
329 if (c == '=')
330 return (tGREATER_EQ);
331 db_unread_char(c);
332 return (tGREATER);
333 case '?':
334 return (tQUESTION);
335 case '~':
336 return (tBIT_NOT);
337 case -1:
338 return (tEOF);
340 db_printf("Bad character\n");
341 db_flush_lex();
342 return (tEOF);