]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/db_lex.c
xnu-792.17.14.tar.gz
[apple/xnu.git] / osfmk / ddb / db_lex.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_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 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.
14 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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 */
155 #include <string.h> /* For strcpy(), strncmp(), strlen() */
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
161 char db_line[DB_LEX_LINE_SIZE];
162 char db_last_line[DB_LEX_LINE_SIZE];
163 char *db_lp, *db_endlp;
164 char *db_last_lp;
165 int db_look_char = 0;
166 db_expr_t db_look_token = 0;
167
168
169 /* Prototypes for functions local to this file. XXX -- should be static!
170 */
171 void db_flush_line(void);
172 void db_unread_char(int c);
173
174
175 int
176 db_read_line(char *repeat_last)
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) {
185 strcpy(db_line, db_last_line);
186 db_printf("%s", db_line);
187 i = strlen(db_line);
188 } else if (db_line[0] != '\n' && db_line[0] != 0)
189 strcpy(db_last_line, db_line);
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
199 void
200 db_flush_line(void)
201 {
202 db_lp = db_line;
203 db_last_lp = db_lp;
204 db_endlp = db_line;
205 }
206
207 void
208 db_switch_input(
209 char *buffer,
210 int size)
211 {
212 db_lp = buffer;
213 db_last_lp = db_lp;
214 db_endlp = buffer + size;
215 db_look_char = 0;
216 db_look_token = 0;
217 }
218
219 void
220 db_save_lex_context(register struct db_lex_context *lp)
221 {
222 lp->l_ptr = db_lp;
223 lp->l_eptr = db_endlp;
224 lp->l_char = db_look_char;
225 lp->l_token = db_look_token;
226 }
227
228 void
229 db_restore_lex_context(register struct db_lex_context *lp)
230 {
231 db_lp = lp->l_ptr;
232 db_last_lp = db_lp;
233 db_endlp = lp->l_eptr;
234 db_look_char = lp->l_char;
235 db_look_token = lp->l_token;
236 }
237
238 int
239 db_read_char(void)
240 {
241 int c;
242
243 if (db_look_char != 0) {
244 c = db_look_char;
245 db_look_char = 0;
246 }
247 else if (db_lp >= db_endlp)
248 c = -1;
249 else
250 c = *db_lp++;
251 return (c);
252 }
253
254 void
255 db_unread_char(int c)
256 {
257 db_look_char = c;
258 }
259
260 void
261 db_unread_token(int t)
262 {
263 db_look_token = t;
264 }
265
266 int
267 db_read_token(void)
268 {
269 int t;
270
271 if (db_look_token) {
272 t = db_look_token;
273 db_look_token = 0;
274 }
275 else {
276 db_last_lp = db_lp;
277 if (db_look_char)
278 db_last_lp--;
279 t = db_lex();
280 }
281 return (t);
282 }
283
284 db_expr_t db_tok_number;
285 char db_tok_string[TOK_STRING_SIZE];
286
287 db_expr_t db_radix = 16;
288
289 void
290 db_flush_lex(void)
291 {
292 db_flush_line();
293 db_look_char = 0;
294 db_look_token = 0;
295 }
296
297 #define DB_DISP_SKIP 40 /* number of chars to display skip */
298
299 void
300 db_skip_to_eol(void)
301 {
302 register int skip;
303 register int t;
304 register int n;
305 register char *p;
306
307 t = db_read_token();
308 p = db_last_lp;
309 for (skip = 0; t != tEOL && t != tSEMI_COLON && t != tEOF; skip++)
310 t = db_read_token();
311 if (t == tSEMI_COLON)
312 db_unread_token(t);
313 if (skip != 0) {
314 while (p < db_last_lp && (*p == ' ' || *p == '\t'))
315 p++;
316 db_printf("Warning: Skipped input data \"");
317 for (n = 0; n < DB_DISP_SKIP && p < db_last_lp; n++)
318 db_printf("%c", *p++);
319 if (n >= DB_DISP_SKIP)
320 db_printf("....");
321 db_printf("\"\n");
322 }
323 }
324
325 int
326 db_lex(void)
327 {
328 register char *cp;
329 register int c;
330
331 c = db_read_char();
332 while (c <= ' ' || c > '~') {
333 if (c == '\n' || c == -1)
334 return (tEOL);
335 c = db_read_char();
336 }
337
338 cp = db_tok_string;
339 *cp++ = c;
340
341 if (c >= '0' && c <= '9') {
342 /* number */
343 int r, digit;
344
345 if (c > '0')
346 r = db_radix;
347 else {
348 c = db_read_char();
349 if (c == 'O' || c == 'o')
350 r = 8;
351 else if (c == 'T' || c == 't')
352 r = 10;
353 else if (c == 'X' || c == 'x')
354 r = 16;
355 else {
356 cp--;
357 r = db_radix;
358 db_unread_char(c);
359 }
360 c = db_read_char();
361 *cp++ = c;
362 }
363 db_tok_number = 0;
364 for (;;) {
365 if (c >= '0' && c <= ((r == 8) ? '7' : '9'))
366 digit = c - '0';
367 else if (r == 16 && ((c >= 'A' && c <= 'F') ||
368 (c >= 'a' && c <= 'f'))) {
369 if (c >= 'a')
370 digit = c - 'a' + 10;
371 else
372 digit = c - 'A' + 10;
373 }
374 else
375 break;
376 db_tok_number = db_tok_number * r + digit;
377 c = db_read_char();
378 if (cp < &db_tok_string[sizeof(db_tok_string)-1])
379 *cp++ = c;
380 }
381 cp[-1] = 0;
382 if ((c >= '0' && c <= '9') ||
383 (c >= 'A' && c <= 'Z') ||
384 (c >= 'a' && c <= 'z') ||
385 (c == '_'))
386 {
387 db_printf("Bad character '%c' after number %s\n",
388 c, db_tok_string);
389 db_error(0);
390 db_flush_lex();
391 return (tEOF);
392 }
393 db_unread_char(c);
394 return (tNUMBER);
395 }
396 if ((c >= 'A' && c <= 'Z') ||
397 (c >= 'a' && c <= 'z') ||
398 c == '_' || c == '\\' || c == ':')
399 {
400 /* identifier */
401 if (c == '\\') {
402 c = db_read_char();
403 if (c == '\n' || c == -1)
404 db_error("Bad '\\' at the end of line\n");
405 cp[-1] = c;
406 }
407 while (1) {
408 c = db_read_char();
409 if ((c >= 'A' && c <= 'Z') ||
410 (c >= 'a' && c <= 'z') ||
411 (c >= '0' && c <= '9') ||
412 c == '_' || c == '\\' || c == ':' || c == '.')
413 {
414 if (c == '\\') {
415 c = db_read_char();
416 if (c == '\n' || c == -1)
417 db_error("Bad '\\' at the end of line\n");
418 }
419 *cp++ = c;
420 if (cp == db_tok_string+sizeof(db_tok_string)) {
421 db_error("String too long\n");
422 db_flush_lex();
423 return (tEOF);
424 }
425 continue;
426 }
427 else {
428 *cp = '\0';
429 break;
430 }
431 }
432 db_unread_char(c);
433 return (tIDENT);
434 }
435
436 *cp = 0;
437 switch (c) {
438 case '+':
439 return (tPLUS);
440 case '-':
441 return (tMINUS);
442 case '.':
443 c = db_read_char();
444 if (c == '.') {
445 *cp++ = c;
446 *cp = 0;
447 return (tDOTDOT);
448 }
449 db_unread_char(c);
450 return (tDOT);
451 case '*':
452 return (tSTAR);
453 case '/':
454 return (tSLASH);
455 case '=':
456 c = db_read_char();
457 if (c == '=') {
458 *cp++ = c;
459 *cp = 0;
460 return(tLOG_EQ);
461 }
462 db_unread_char(c);
463 return (tEQ);
464 case '%':
465 return (tPCT);
466 case '#':
467 return (tHASH);
468 case '(':
469 return (tLPAREN);
470 case ')':
471 return (tRPAREN);
472 case ',':
473 return (tCOMMA);
474 case '\'':
475 return (tQUOTE);
476 case '"':
477 /* string */
478 cp = db_tok_string;
479 c = db_read_char();
480 while (c != '"' && c > 0 && c != '\n') {
481 if (cp >= &db_tok_string[sizeof(db_tok_string)-1]) {
482 db_error("Too long string\n");
483 db_flush_lex();
484 return (tEOF);
485 }
486 if (c == '\\') {
487 c = db_read_char();
488 switch(c) {
489 case 'n':
490 c = '\n'; break;
491 case 't':
492 c = '\t'; break;
493 case '\\':
494 case '"':
495 break;
496 default:
497 db_printf("Bad escape sequence '\\%c'\n", c);
498 db_error(0);
499 db_flush_lex();
500 return (tEOF);
501 }
502 }
503 *cp++ = c;
504 c = db_read_char();
505 }
506 *cp = 0;
507 if (c != '"') {
508 db_error("Non terminated string constant\n");
509 db_flush_lex();
510 return (tEOF);
511 }
512 return (tSTRING);
513 case '$':
514 return (tDOLLAR);
515 case '!':
516 c = db_read_char();
517 if (c == '=') {
518 *cp++ = c;
519 *cp = 0;
520 return(tLOG_NOT_EQ);
521 }
522 db_unread_char(c);
523 return (tEXCL);
524 case '&':
525 c = db_read_char();
526 if (c == '&') {
527 *cp++ = c;
528 *cp = 0;
529 return(tLOG_AND);
530 }
531 db_unread_char(c);
532 return(tBIT_AND);
533 case '|':
534 c = db_read_char();
535 if (c == '|') {
536 *cp++ = c;
537 *cp = 0;
538 return(tLOG_OR);
539 }
540 db_unread_char(c);
541 return(tBIT_OR);
542 case '<':
543 c = db_read_char();
544 *cp++ = c;
545 *cp = 0;
546 if (c == '<')
547 return (tSHIFT_L);
548 if (c == '=')
549 return (tLESS_EQ);
550 cp[-1] = 0;
551 db_unread_char(c);
552 return(tLESS);
553 break;
554 case '>':
555 c = db_read_char();
556 *cp++ = c;
557 *cp = 0;
558 if (c == '>')
559 return (tSHIFT_R);
560 if (c == '=')
561 return (tGREATER_EQ);
562 cp[-1] = 0;
563 db_unread_char(c);
564 return (tGREATER);
565 break;
566 case ';':
567 return (tSEMI_COLON);
568 case '?':
569 return (tQUESTION);
570 case -1:
571 strcpy(db_tok_string, "<EOL>");
572 return (tEOF);
573 }
574 db_printf("Bad character '%c'\n", c);
575 db_flush_lex();
576 return (tEOF);
577 }