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