FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_lex.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,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 "AS IS"
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 Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: db_lex.c,v $
29 * Revision 2.10 93/11/17 16:22:46 dbg
30 * Added prototypes.
31 * [93/10/06 dbg]
32 *
33 * Revision 2.9 93/03/09 10:53:39 danner
34 * String protos.
35 * [93/03/07 af]
36 *
37 * Revision 2.8 93/01/14 17:25:07 danner
38 * 64bit cleanup.
39 * [92/11/30 af]
40 *
41 * Revision 2.7 92/08/03 17:31:28 jfriedl
42 * removed silly prototypes
43 * [92/08/02 jfriedl]
44 *
45 * Revision 2.6 92/05/21 17:07:10 jfriedl
46 * Cleanup to quiet gcc warnings.
47 * [92/05/18 jfriedl]
48 *
49 * Revision 2.5 91/10/09 16:00:20 af
50 * Added relational operator tokens and string constant etc.
51 * Added input switching functions for macro and conditional command.
52 * Moved skip_to_eol() from db_command.c and added db_last_lp to print
53 * skipped input data as a warning message.
54 * Added last input repetition support to db_read_line.
55 * Changed db_lex() to always set db_tok_string for error message.
56 * [91/08/29 tak]
57 *
58 * Revision 2.4 91/05/14 15:34:23 mrt
59 * Correcting copyright
60 *
61 * Revision 2.3 91/02/05 17:06:36 mrt
62 * Changed to new Mach copyright
63 * [91/01/31 16:18:20 mrt]
64 *
65 * Revision 2.2 90/08/27 21:51:10 dbg
66 * Add 'dotdot' token.
67 * [90/08/22 dbg]
68 *
69 * Allow backslash to quote any character into an identifier.
70 * Allow colon in identifier for symbol table qualification.
71 * [90/08/16 dbg]
72 * Reduce lint.
73 * [90/08/07 dbg]
74 * Created.
75 * [90/07/25 dbg]
76 *
77 */
78 /*
79 * Author: David B. Golub, Carnegie Mellon University
80 * Date: 7/90
81 */
82 /*
83 * Lexical analyzer.
84 */
85 #include <machine/db_machdep.h>
86 #include <kern/strings.h>
87 #include <ddb/db_command.h> /* db_error */
88 #include <ddb/db_lex.h>
89 #include <ddb/db_input.h>
90 #include <ddb/db_output.h>
91
92 char db_line[DB_LEX_LINE_SIZE];
93 char db_last_line[DB_LEX_LINE_SIZE];
94 char *db_lp, *db_endlp;
95 char *db_last_lp;
96 int db_look_char = 0;
97 db_expr_t db_look_token = 0;
98
99 int db_lex(void); /* forward */
100
101 int
102 db_read_line(
103 char *repeat_last)
104 {
105 int i;
106
107 i = db_readline(db_line, sizeof(db_line));
108 if (i == 0)
109 return 0; /* EOI */
110 if (repeat_last) {
111 if (strncmp(db_line, repeat_last, strlen(repeat_last)) == 0) {
112 strcpy(db_line, db_last_line);
113 db_printf("%s", db_line);
114 i = strlen(db_line);
115 } else if (db_line[0] != '\n' && db_line[0] != 0)
116 strcpy(db_last_line, db_line);
117 }
118 db_lp = db_line;
119 db_endlp = db_lp + i;
120 db_last_lp = db_lp;
121 db_look_char = 0;
122 db_look_token = 0;
123 return i;
124 }
125
126 void
127 db_flush_line(void)
128 {
129 db_lp = db_line;
130 db_last_lp = db_lp;
131 db_endlp = db_line;
132 }
133
134 void
135 db_switch_input(
136 char *buffer,
137 int size)
138 {
139 db_lp = buffer;
140 db_last_lp = db_lp;
141 db_endlp = buffer + size;
142 db_look_char = 0;
143 db_look_token = 0;
144 }
145
146 void
147 db_save_lex_context(
148 register struct db_lex_context *lp)
149 {
150 lp->l_ptr = db_lp;
151 lp->l_eptr = db_endlp;
152 lp->l_char = db_look_char;
153 lp->l_token = db_look_token;
154 }
155
156 void
157 db_restore_lex_context(
158 register struct db_lex_context *lp)
159 {
160 db_lp = lp->l_ptr;
161 db_last_lp = db_lp;
162 db_endlp = lp->l_eptr;
163 db_look_char = lp->l_char;
164 db_look_token = lp->l_token;
165 }
166
167 int
168 db_read_char(void)
169 {
170 int c;
171
172 if (db_look_char != 0) {
173 c = db_look_char;
174 db_look_char = 0;
175 }
176 else if (db_lp >= db_endlp)
177 c = -1;
178 else
179 c = *db_lp++;
180 return c;
181 }
182
183 void
184 db_unread_char(
185 int c)
186 {
187 db_look_char = c;
188 }
189
190 void
191 db_unread_token(
192 int t)
193 {
194 db_look_token = t;
195 }
196
197 int
198 db_read_token(void)
199 {
200 int t;
201
202 if (db_look_token) {
203 t = db_look_token;
204 db_look_token = 0;
205 }
206 else {
207 db_last_lp = db_lp;
208 if (db_look_char)
209 db_last_lp--;
210 t = db_lex();
211 }
212 return t;
213 }
214
215 db_expr_t db_tok_number;
216 char db_tok_string[TOK_STRING_SIZE];
217 db_expr_t db_radix = 16;
218
219 void
220 db_flush_lex(void)
221 {
222 db_flush_line();
223 db_look_char = 0;
224 db_look_token = 0;
225 }
226
227 #define DB_DISP_SKIP 40 /* number of chars to display skip */
228
229 void
230 db_skip_to_eol(void)
231 {
232 register skip;
233 register t;
234 register n;
235 register char *p;
236
237 t = db_read_token();
238 p = db_last_lp;
239 for (skip = 0; t != tEOL && t != tSEMI_COLON && t != tEOF; skip++)
240 t = db_read_token();
241 if (t == tSEMI_COLON)
242 db_unread_token(t);
243 if (skip != 0) {
244 while (p < db_last_lp && (*p == ' ' || *p == '\t'))
245 p++;
246 db_printf("Warning: Skipped input data \"");
247 for (n = 0; n < DB_DISP_SKIP && p < db_last_lp; n++)
248 db_printf("%c", *p++);
249 if (n >= DB_DISP_SKIP)
250 db_printf("....");
251 db_printf("\"\n");
252 }
253 }
254
255 int
256 db_lex(void)
257 {
258 register char *cp;
259 register c;
260
261 c = db_read_char();
262 while (c <= ' ' || c > '~') {
263 if (c == '\n' || c == -1)
264 return (tEOL);
265 c = db_read_char();
266 }
267
268 cp = db_tok_string;
269 *cp++ = c;
270
271 if (c >= '' && c <= '9') {
272 /* number */
273 int r, digit;
274
275 if (c > '')
276 r = db_radix;
277 else {
278 c = db_read_char();
279 if (c == 'O' || c == 'o')
280 r = 8;
281 else if (c == 'T' || c == 't')
282 r = 10;
283 else if (c == 'X' || c == 'x')
284 r = 16;
285 else {
286 cp--;
287 r = db_radix;
288 db_unread_char(c);
289 }
290 c = db_read_char();
291 *cp++ = c;
292 }
293 db_tok_number = 0;
294 for (;;) {
295 if (c >= '' && c <= ((r == 8) ? '7' : '9'))
296 digit = c - '';
297 else if (r == 16 && ((c >= 'A' && c <= 'F') ||
298 (c >= 'a' && c <= 'f'))) {
299 if (c >= 'a')
300 digit = c - 'a' + 10;
301 else
302 digit = c - 'A' + 10;
303 }
304 else
305 break;
306 db_tok_number = db_tok_number * r + digit;
307 c = db_read_char();
308 if (cp < &db_tok_string[sizeof(db_tok_string)-1])
309 *cp++ = c;
310 }
311 cp[-1] = 0;
312 if ((c >= '' && c <= '9') ||
313 (c >= 'A' && c <= 'Z') ||
314 (c >= 'a' && c <= 'z') ||
315 (c == '_'))
316 {
317 db_printf("Bad character '%c' after number %s\n",
318 c, db_tok_string);
319 db_error(0);
320 db_flush_lex();
321 return tEOF;
322 }
323 db_unread_char(c);
324 return tNUMBER;
325 }
326 if ((c >= 'A' && c <= 'Z') ||
327 (c >= 'a' && c <= 'z') ||
328 c == '_' || c == '\\' || c == ':')
329 {
330 /* identifier */
331 if (c == '\\') {
332 c = db_read_char();
333 if (c == '\n' || c == -1)
334 db_error("Bad '\\' at the end of line\n");
335 cp[-1] = c;
336 }
337 while (1) {
338 c = db_read_char();
339 if ((c >= 'A' && c <= 'Z') ||
340 (c >= 'a' && c <= 'z') ||
341 (c >= '' && c <= '9') ||
342 c == '_' || c == '\\' || c == ':' || c == '.')
343 {
344 if (c == '\\') {
345 c = db_read_char();
346 if (c == '\n' || c == -1)
347 db_error("Bad '\\' at the end of line\n");
348 }
349 *cp++ = c;
350 if (cp == db_tok_string+sizeof(db_tok_string)) {
351 db_error("String too long\n");
352 db_flush_lex();
353 return tEOF;
354 }
355 continue;
356 }
357 else {
358 *cp = '\0';
359 break;
360 }
361 }
362 db_unread_char(c);
363 return tIDENT;
364 }
365
366 *cp = 0;
367 switch (c) {
368 case '+':
369 return tPLUS;
370 case '-':
371 return tMINUS;
372 case '.':
373 c = db_read_char();
374 if (c == '.') {
375 *cp++ = c;
376 *cp = 0;
377 return tDOTDOT;
378 }
379 db_unread_char(c);
380 return tDOT;
381 case '*':
382 return tSTAR;
383 case '/':
384 return tSLASH;
385 case '=':
386 c = db_read_char();
387 if (c == '=') {
388 *cp++ = c;
389 *cp = 0;
390 return tLOG_EQ;
391 }
392 db_unread_char(c);
393 return tEQ;
394 case '%':
395 return tPCT;
396 case '#':
397 return tHASH;
398 case '(':
399 return tLPAREN;
400 case ')':
401 return tRPAREN;
402 case ',':
403 return tCOMMA;
404 case '\'':
405 return tQUOTE;
406 case '"':
407 /* string */
408 cp = db_tok_string;
409 c = db_read_char();
410 while (c != '"' && c > 0 && c != '\n') {
411 if (cp >= &db_tok_string[sizeof(db_tok_string)-1]) {
412 db_error("Too long string\n");
413 db_flush_lex();
414 return tEOF;
415 }
416 if (c == '\\') {
417 c = db_read_char();
418 switch(c) {
419 case 'n':
420 c = '\n'; break;
421 case 't':
422 c = '\t'; break;
423 case '\\':
424 case '"':
425 break;
426 default:
427 db_printf("Bad escape sequence '\\%c'\n", c);
428 db_error(0);
429 db_flush_lex();
430 return tEOF;
431 }
432 }
433 *cp++ = c;
434 c = db_read_char();
435 }
436 *cp = 0;
437 if (c != '"') {
438 db_error("Non terminated string constant\n");
439 db_flush_lex();
440 return tEOF;
441 }
442 return tSTRING;
443 case '$':
444 return tDOLLAR;
445 case '!':
446 c = db_read_char();
447 if (c == '=') {
448 *cp++ = c;
449 *cp = 0;
450 return tLOG_NOT_EQ;
451 }
452 db_unread_char(c);
453 return tEXCL;
454 case '&':
455 c = db_read_char();
456 if (c == '&') {
457 *cp++ = c;
458 *cp = 0;
459 return tLOG_AND;
460 }
461 db_unread_char(c);
462 return tBIT_AND;
463 case '|':
464 c = db_read_char();
465 if (c == '|') {
466 *cp++ = c;
467 *cp = 0;
468 return tLOG_OR;
469 }
470 db_unread_char(c);
471 return tBIT_OR;
472 case '<':
473 c = db_read_char();
474 *cp++ = c;
475 *cp = 0;
476 if (c == '<')
477 return tSHIFT_L;
478 if (c == '=')
479 return tLESS_EQ;
480 cp[-1] = 0;
481 db_unread_char(c);
482 return tLESS;
483 break;
484 case '>':
485 c = db_read_char();
486 *cp++ = c;
487 *cp = 0;
488 if (c == '>')
489 return tSHIFT_R;
490 if (c == '=')
491 return tGREATER_EQ;
492 cp[-1] = 0;
493 db_unread_char(c);
494 return tGREATER;
495 break;
496 case ';':
497 return tSEMI_COLON;
498 case '?':
499 return tQUESTION;
500 case -1:
501 strcpy(db_tok_string, "<EOL>");
502 return tEOF;
503 }
504 db_printf("Bad character '%c'\n", c);
505 db_flush_lex();
506 return tEOF;
507 }
Cache object: 99d16445e6806d678bdc6d54711a74da
|