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