]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/db_lex.c
xnu-792.12.6.tar.gz
[apple/xnu.git] / osfmk / ddb / db_lex.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30 /*
31 * @OSF_COPYRIGHT@
32 */
33 /*
34 * HISTORY
35 *
36 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
37 * Import of Mac OS X kernel (~semeria)
38 *
39 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
40 * Import of OSF Mach kernel (~mburg)
41 *
42 * Revision 1.1.11.3 1996/01/09 19:15:49 devrcs
43 * Change 'register foo' to 'register int foo'.
44 * [1995/12/01 21:42:12 jfraser]
45 *
46 * Merged '64-bit safe' changes from DEC alpha port.
47 * [1995/11/21 18:03:11 jfraser]
48 *
49 * Revision 1.1.11.2 1995/01/06 19:10:21 devrcs
50 * mk6 CR668 - 1.3b26 merge
51 * * Revision 1.1.4.6 1994/05/06 18:39:20 tmt
52 * Merged osc1.3dec/shared with osc1.3b19
53 * Merge Alpha changes into osc1.312b source code.
54 * String protos.
55 * 64bit cleanup.
56 * Cleanup to quiet gcc warnings.
57 * * End1.3merge
58 * [1994/11/04 08:49:35 dwm]
59 *
60 * Revision 1.1.11.1 1994/09/23 01:19:59 ezf
61 * change marker to not FREE
62 * [1994/09/22 21:10:14 ezf]
63 *
64 * Revision 1.1.4.4 1993/08/11 20:37:55 elliston
65 * Add ANSI Prototypes. CR #9523.
66 * [1993/08/11 03:33:26 elliston]
67 *
68 * Revision 1.1.4.3 1993/07/27 18:27:38 elliston
69 * Add ANSI prototypes. CR #9523.
70 * [1993/07/27 18:12:13 elliston]
71 *
72 * Revision 1.1.4.2 1993/06/02 23:11:27 jeffc
73 * Added to OSF/1 R1.3 from NMK15.0.
74 * [1993/06/02 20:56:32 jeffc]
75 *
76 * Revision 1.1 1992/09/30 02:01:10 robert
77 * Initial revision
78 *
79 * $EndLog$
80 */
81 /* CMU_HIST */
82 /*
83 * Revision 2.5 91/10/09 16:00:20 af
84 * Revision 2.4.3.1 91/10/05 13:06:25 jeffreyh
85 * Added relational operator tokens and string constant etc.
86 * Added input switching functions for macro and conditional command.
87 * Moved skip_to_eol() from db_command.c and added db_last_lp to print
88 * skipped input data as a warning message.
89 * Added last input repetition support to db_read_line.
90 * Changed db_lex() to always set db_tok_string for error message.
91 * [91/08/29 tak]
92 *
93 * Revision 2.4.3.1 91/10/05 13:06:25 jeffreyh
94 * Added relational operator tokens and string constant etc.
95 * Added input switching functions for macro and conditional command.
96 * Moved skip_to_eol() from db_command.c and added db_last_lp to print
97 * skipped input data as a warning message.
98 * Added last input repetition support to db_read_line.
99 * Changed db_lex() to always set db_tok_string for error message.
100 * [91/08/29 tak]
101 *
102 * Revision 2.4 91/05/14 15:34:23 mrt
103 * Correcting copyright
104 *
105 * Revision 2.3 91/02/05 17:06:36 mrt
106 * Changed to new Mach copyright
107 * [91/01/31 16:18:20 mrt]
108 *
109 * Revision 2.2 90/08/27 21:51:10 dbg
110 * Add 'dotdot' token.
111 * [90/08/22 dbg]
112 *
113 * Allow backslash to quote any character into an identifier.
114 * Allow colon in identifier for symbol table qualification.
115 * [90/08/16 dbg]
116 * Reduce lint.
117 * [90/08/07 dbg]
118 * Created.
119 * [90/07/25 dbg]
120 *
121 */
122 /* CMU_ENDHIST */
123 /*
124 * Mach Operating System
125 * Copyright (c) 1991,1990 Carnegie Mellon University
126 * All Rights Reserved.
127 *
128 * Permission to use, copy, modify and distribute this software and its
129 * documentation is hereby granted, provided that both the copyright
130 * notice and this permission notice appear in all copies of the
131 * software, derivative works or modified versions, and any portions
132 * thereof, and that both notices appear in supporting documentation.
133 *
134 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
135 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
136 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
137 *
138 * Carnegie Mellon requests users of this software to return to
139 *
140 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
141 * School of Computer Science
142 * Carnegie Mellon University
143 * Pittsburgh PA 15213-3890
144 *
145 * any improvements or extensions that they make and grant Carnegie Mellon
146 * the rights to redistribute these changes.
147 */
148 /*
149 */
150 /*
151 * Author: David B. Golub, Carnegie Mellon University
152 * Date: 7/90
153 */
154 /*
155 * Lexical analyzer.
156 */
157 #include <string.h> /* For strcpy(), strncmp(), strlen() */
158 #include <ddb/db_lex.h>
159 #include <ddb/db_command.h>
160 #include <ddb/db_input.h>
161 #include <ddb/db_output.h> /* For db_printf() */
162
163 char db_line[DB_LEX_LINE_SIZE];
164 char db_last_line[DB_LEX_LINE_SIZE];
165 char *db_lp, *db_endlp;
166 char *db_last_lp;
167 int db_look_char = 0;
168 db_expr_t db_look_token = 0;
169
170
171 /* Prototypes for functions local to this file. XXX -- should be static!
172 */
173 void db_flush_line(void);
174 void db_unread_char(int c);
175
176
177 int
178 db_read_line(char *repeat_last)
179 {
180 int i;
181
182 i = db_readline(db_line, sizeof(db_line));
183 if (i == 0)
184 return (0); /* EOI */
185 if (repeat_last) {
186 if (strncmp(db_line, repeat_last, strlen(repeat_last)) == 0) {
187 strcpy(db_line, db_last_line);
188 db_printf("%s", db_line);
189 i = strlen(db_line);
190 } else if (db_line[0] != '\n' && db_line[0] != 0)
191 strcpy(db_last_line, db_line);
192 }
193 db_lp = db_line;
194 db_endlp = db_lp + i;
195 db_last_lp = db_lp;
196 db_look_char = 0;
197 db_look_token = 0;
198 return (i);
199 }
200
201 void
202 db_flush_line(void)
203 {
204 db_lp = db_line;
205 db_last_lp = db_lp;
206 db_endlp = db_line;
207 }
208
209 void
210 db_switch_input(
211 char *buffer,
212 int size)
213 {
214 db_lp = buffer;
215 db_last_lp = db_lp;
216 db_endlp = buffer + size;
217 db_look_char = 0;
218 db_look_token = 0;
219 }
220
221 void
222 db_save_lex_context(register struct db_lex_context *lp)
223 {
224 lp->l_ptr = db_lp;
225 lp->l_eptr = db_endlp;
226 lp->l_char = db_look_char;
227 lp->l_token = db_look_token;
228 }
229
230 void
231 db_restore_lex_context(register struct db_lex_context *lp)
232 {
233 db_lp = lp->l_ptr;
234 db_last_lp = db_lp;
235 db_endlp = lp->l_eptr;
236 db_look_char = lp->l_char;
237 db_look_token = lp->l_token;
238 }
239
240 int
241 db_read_char(void)
242 {
243 int c;
244
245 if (db_look_char != 0) {
246 c = db_look_char;
247 db_look_char = 0;
248 }
249 else if (db_lp >= db_endlp)
250 c = -1;
251 else
252 c = *db_lp++;
253 return (c);
254 }
255
256 void
257 db_unread_char(int c)
258 {
259 db_look_char = c;
260 }
261
262 void
263 db_unread_token(int t)
264 {
265 db_look_token = t;
266 }
267
268 int
269 db_read_token(void)
270 {
271 int t;
272
273 if (db_look_token) {
274 t = db_look_token;
275 db_look_token = 0;
276 }
277 else {
278 db_last_lp = db_lp;
279 if (db_look_char)
280 db_last_lp--;
281 t = db_lex();
282 }
283 return (t);
284 }
285
286 db_expr_t db_tok_number;
287 char db_tok_string[TOK_STRING_SIZE];
288
289 db_expr_t db_radix = 16;
290
291 void
292 db_flush_lex(void)
293 {
294 db_flush_line();
295 db_look_char = 0;
296 db_look_token = 0;
297 }
298
299 #define DB_DISP_SKIP 40 /* number of chars to display skip */
300
301 void
302 db_skip_to_eol(void)
303 {
304 register int skip;
305 register int t;
306 register int n;
307 register char *p;
308
309 t = db_read_token();
310 p = db_last_lp;
311 for (skip = 0; t != tEOL && t != tSEMI_COLON && t != tEOF; skip++)
312 t = db_read_token();
313 if (t == tSEMI_COLON)
314 db_unread_token(t);
315 if (skip != 0) {
316 while (p < db_last_lp && (*p == ' ' || *p == '\t'))
317 p++;
318 db_printf("Warning: Skipped input data \"");
319 for (n = 0; n < DB_DISP_SKIP && p < db_last_lp; n++)
320 db_printf("%c", *p++);
321 if (n >= DB_DISP_SKIP)
322 db_printf("....");
323 db_printf("\"\n");
324 }
325 }
326
327 int
328 db_lex(void)
329 {
330 register char *cp;
331 register int c;
332
333 c = db_read_char();
334 while (c <= ' ' || c > '~') {
335 if (c == '\n' || c == -1)
336 return (tEOL);
337 c = db_read_char();
338 }
339
340 cp = db_tok_string;
341 *cp++ = c;
342
343 if (c >= '0' && c <= '9') {
344 /* number */
345 int r, digit;
346
347 if (c > '0')
348 r = db_radix;
349 else {
350 c = db_read_char();
351 if (c == 'O' || c == 'o')
352 r = 8;
353 else if (c == 'T' || c == 't')
354 r = 10;
355 else if (c == 'X' || c == 'x')
356 r = 16;
357 else {
358 cp--;
359 r = db_radix;
360 db_unread_char(c);
361 }
362 c = db_read_char();
363 *cp++ = c;
364 }
365 db_tok_number = 0;
366 for (;;) {
367 if (c >= '0' && c <= ((r == 8) ? '7' : '9'))
368 digit = c - '0';
369 else if (r == 16 && ((c >= 'A' && c <= 'F') ||
370 (c >= 'a' && c <= 'f'))) {
371 if (c >= 'a')
372 digit = c - 'a' + 10;
373 else
374 digit = c - 'A' + 10;
375 }
376 else
377 break;
378 db_tok_number = db_tok_number * r + digit;
379 c = db_read_char();
380 if (cp < &db_tok_string[sizeof(db_tok_string)-1])
381 *cp++ = c;
382 }
383 cp[-1] = 0;
384 if ((c >= '0' && c <= '9') ||
385 (c >= 'A' && c <= 'Z') ||
386 (c >= 'a' && c <= 'z') ||
387 (c == '_'))
388 {
389 db_printf("Bad character '%c' after number %s\n",
390 c, db_tok_string);
391 db_error(0);
392 db_flush_lex();
393 return (tEOF);
394 }
395 db_unread_char(c);
396 return (tNUMBER);
397 }
398 if ((c >= 'A' && c <= 'Z') ||
399 (c >= 'a' && c <= 'z') ||
400 c == '_' || c == '\\' || c == ':')
401 {
402 /* identifier */
403 if (c == '\\') {
404 c = db_read_char();
405 if (c == '\n' || c == -1)
406 db_error("Bad '\\' at the end of line\n");
407 cp[-1] = c;
408 }
409 while (1) {
410 c = db_read_char();
411 if ((c >= 'A' && c <= 'Z') ||
412 (c >= 'a' && c <= 'z') ||
413 (c >= '0' && c <= '9') ||
414 c == '_' || c == '\\' || c == ':' || c == '.')
415 {
416 if (c == '\\') {
417 c = db_read_char();
418 if (c == '\n' || c == -1)
419 db_error("Bad '\\' at the end of line\n");
420 }
421 *cp++ = c;
422 if (cp == db_tok_string+sizeof(db_tok_string)) {
423 db_error("String too long\n");
424 db_flush_lex();
425 return (tEOF);
426 }
427 continue;
428 }
429 else {
430 *cp = '\0';
431 break;
432 }
433 }
434 db_unread_char(c);
435 return (tIDENT);
436 }
437
438 *cp = 0;
439 switch (c) {
440 case '+':
441 return (tPLUS);
442 case '-':
443 return (tMINUS);
444 case '.':
445 c = db_read_char();
446 if (c == '.') {
447 *cp++ = c;
448 *cp = 0;
449 return (tDOTDOT);
450 }
451 db_unread_char(c);
452 return (tDOT);
453 case '*':
454 return (tSTAR);
455 case '/':
456 return (tSLASH);
457 case '=':
458 c = db_read_char();
459 if (c == '=') {
460 *cp++ = c;
461 *cp = 0;
462 return(tLOG_EQ);
463 }
464 db_unread_char(c);
465 return (tEQ);
466 case '%':
467 return (tPCT);
468 case '#':
469 return (tHASH);
470 case '(':
471 return (tLPAREN);
472 case ')':
473 return (tRPAREN);
474 case ',':
475 return (tCOMMA);
476 case '\'':
477 return (tQUOTE);
478 case '"':
479 /* string */
480 cp = db_tok_string;
481 c = db_read_char();
482 while (c != '"' && c > 0 && c != '\n') {
483 if (cp >= &db_tok_string[sizeof(db_tok_string)-1]) {
484 db_error("Too long string\n");
485 db_flush_lex();
486 return (tEOF);
487 }
488 if (c == '\\') {
489 c = db_read_char();
490 switch(c) {
491 case 'n':
492 c = '\n'; break;
493 case 't':
494 c = '\t'; break;
495 case '\\':
496 case '"':
497 break;
498 default:
499 db_printf("Bad escape sequence '\\%c'\n", c);
500 db_error(0);
501 db_flush_lex();
502 return (tEOF);
503 }
504 }
505 *cp++ = c;
506 c = db_read_char();
507 }
508 *cp = 0;
509 if (c != '"') {
510 db_error("Non terminated string constant\n");
511 db_flush_lex();
512 return (tEOF);
513 }
514 return (tSTRING);
515 case '$':
516 return (tDOLLAR);
517 case '!':
518 c = db_read_char();
519 if (c == '=') {
520 *cp++ = c;
521 *cp = 0;
522 return(tLOG_NOT_EQ);
523 }
524 db_unread_char(c);
525 return (tEXCL);
526 case '&':
527 c = db_read_char();
528 if (c == '&') {
529 *cp++ = c;
530 *cp = 0;
531 return(tLOG_AND);
532 }
533 db_unread_char(c);
534 return(tBIT_AND);
535 case '|':
536 c = db_read_char();
537 if (c == '|') {
538 *cp++ = c;
539 *cp = 0;
540 return(tLOG_OR);
541 }
542 db_unread_char(c);
543 return(tBIT_OR);
544 case '<':
545 c = db_read_char();
546 *cp++ = c;
547 *cp = 0;
548 if (c == '<')
549 return (tSHIFT_L);
550 if (c == '=')
551 return (tLESS_EQ);
552 cp[-1] = 0;
553 db_unread_char(c);
554 return(tLESS);
555 break;
556 case '>':
557 c = db_read_char();
558 *cp++ = c;
559 *cp = 0;
560 if (c == '>')
561 return (tSHIFT_R);
562 if (c == '=')
563 return (tGREATER_EQ);
564 cp[-1] = 0;
565 db_unread_char(c);
566 return (tGREATER);
567 break;
568 case ';':
569 return (tSEMI_COLON);
570 case '?':
571 return (tQUESTION);
572 case -1:
573 strcpy(db_tok_string, "<EOL>");
574 return (tEOF);
575 }
576 db_printf("Bad character '%c'\n", c);
577 db_flush_lex();
578 return (tEOF);
579 }