1dd3cb568SWarner Losh /*-
2796df753SPedro F. Giffuni * SPDX-License-Identifier: MIT-CMU
3796df753SPedro F. Giffuni *
45b81b6b3SRodney W. Grimes * Mach Operating System
55b81b6b3SRodney W. Grimes * Copyright (c) 1991,1990 Carnegie Mellon University
65b81b6b3SRodney W. Grimes * All Rights Reserved.
75b81b6b3SRodney W. Grimes *
85b81b6b3SRodney W. Grimes * Permission to use, copy, modify and distribute this software and its
95b81b6b3SRodney W. Grimes * documentation is hereby granted, provided that both the copyright
105b81b6b3SRodney W. Grimes * notice and this permission notice appear in all copies of the
115b81b6b3SRodney W. Grimes * software, derivative works or modified versions, and any portions
125b81b6b3SRodney W. Grimes * thereof, and that both notices appear in supporting documentation.
135b81b6b3SRodney W. Grimes *
145b81b6b3SRodney W. Grimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
155b81b6b3SRodney W. Grimes * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
165b81b6b3SRodney W. Grimes * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
175b81b6b3SRodney W. Grimes *
185b81b6b3SRodney W. Grimes * Carnegie Mellon requests users of this software to return to
195b81b6b3SRodney W. Grimes *
205b81b6b3SRodney W. Grimes * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
215b81b6b3SRodney W. Grimes * School of Computer Science
225b81b6b3SRodney W. Grimes * Carnegie Mellon University
235b81b6b3SRodney W. Grimes * Pittsburgh PA 15213-3890
245b81b6b3SRodney W. Grimes *
255b81b6b3SRodney W. Grimes * any improvements or extensions that they make and grant Carnegie the
265b81b6b3SRodney W. Grimes * rights to redistribute these changes.
275b81b6b3SRodney W. Grimes */
285b81b6b3SRodney W. Grimes /*
295b81b6b3SRodney W. Grimes * Author: David B. Golub, Carnegie Mellon University
305b81b6b3SRodney W. Grimes * Date: 7/90
315b81b6b3SRodney W. Grimes */
325b81b6b3SRodney W. Grimes /*
335b81b6b3SRodney W. Grimes * Lexical analyzer.
345b81b6b3SRodney W. Grimes */
35753960f7SDavid E. O'Brien
36f540b106SGarrett Wollman #include <sys/param.h>
37c9b0cc3bSRobert Watson #include <sys/libkern.h>
38e0c5dd43SConrad Meyer #include <sys/lock.h>
395ccbc3ccSBruce Evans
40f540b106SGarrett Wollman #include <ddb/ddb.h>
415b81b6b3SRodney W. Grimes #include <ddb/db_lex.h>
425b81b6b3SRodney W. Grimes
43c9b0cc3bSRobert Watson static char db_line[DB_MAXLINE];
4425eb640dSPoul-Henning Kamp static char * db_lp, *db_endlp;
455b81b6b3SRodney W. Grimes
46e0c5dd43SConrad Meyer static int db_lex(int);
4714e10f99SAlfred Perlstein static void db_flush_line(void);
4814e10f99SAlfred Perlstein static int db_read_char(void);
4914e10f99SAlfred Perlstein static void db_unread_char(int);
50f23b4c91SGarrett Wollman
515b81b6b3SRodney W. Grimes int
db_read_line(void)52a41dd031SPedro F. Giffuni db_read_line(void)
535b81b6b3SRodney W. Grimes {
545b81b6b3SRodney W. Grimes int i;
555b81b6b3SRodney W. Grimes
565b81b6b3SRodney W. Grimes i = db_readline(db_line, sizeof(db_line));
575b81b6b3SRodney W. Grimes if (i == 0)
585b81b6b3SRodney W. Grimes return (0); /* EOI */
595b81b6b3SRodney W. Grimes db_lp = db_line;
605b81b6b3SRodney W. Grimes db_endlp = db_lp + i;
615b81b6b3SRodney W. Grimes return (i);
625b81b6b3SRodney W. Grimes }
635b81b6b3SRodney W. Grimes
64c9b0cc3bSRobert Watson /*
65c9b0cc3bSRobert Watson * Simulate a line of input into DDB.
66c9b0cc3bSRobert Watson */
67c9b0cc3bSRobert Watson void
db_inject_line(const char * command)68c9b0cc3bSRobert Watson db_inject_line(const char *command)
69c9b0cc3bSRobert Watson {
70c9b0cc3bSRobert Watson
71c9b0cc3bSRobert Watson strlcpy(db_line, command, sizeof(db_line));
72c9b0cc3bSRobert Watson db_lp = db_line;
73c9b0cc3bSRobert Watson db_endlp = db_lp + strlen(command);
74c9b0cc3bSRobert Watson }
75c9b0cc3bSRobert Watson
76c9b0cc3bSRobert Watson /*
77c9b0cc3bSRobert Watson * In rare cases, we may want to pull the remainder of the line input
78c9b0cc3bSRobert Watson * verbatim, rather than lexing it. For example, when assigning literal
79c9b0cc3bSRobert Watson * values associated with scripts. In that case, return a static pointer to
80c9b0cc3bSRobert Watson * the current location in the input buffer. The caller must be aware that
81c9b0cc3bSRobert Watson * the contents are not stable if other lex/input calls are made.
82c9b0cc3bSRobert Watson */
83c9b0cc3bSRobert Watson char *
db_get_line(void)84c9b0cc3bSRobert Watson db_get_line(void)
85c9b0cc3bSRobert Watson {
86c9b0cc3bSRobert Watson
87c9b0cc3bSRobert Watson return (db_lp);
88c9b0cc3bSRobert Watson }
89c9b0cc3bSRobert Watson
90f73a856dSPoul-Henning Kamp static void
db_flush_line(void)91*939cb349SDimitry Andric db_flush_line(void)
925b81b6b3SRodney W. Grimes {
935b81b6b3SRodney W. Grimes db_lp = db_line;
945b81b6b3SRodney W. Grimes db_endlp = db_line;
955b81b6b3SRodney W. Grimes }
965b81b6b3SRodney W. Grimes
97f73a856dSPoul-Henning Kamp static int
db_read_char(void)98a41dd031SPedro F. Giffuni db_read_char(void)
995b81b6b3SRodney W. Grimes {
1005b81b6b3SRodney W. Grimes int c;
1015b81b6b3SRodney W. Grimes
102d8404b7eSRyan Libby if (db_lp >= db_endlp)
1035b81b6b3SRodney W. Grimes c = -1;
1045b81b6b3SRodney W. Grimes else
1055b81b6b3SRodney W. Grimes c = *db_lp++;
1065b81b6b3SRodney W. Grimes return (c);
1075b81b6b3SRodney W. Grimes }
1085b81b6b3SRodney W. Grimes
109f73a856dSPoul-Henning Kamp static void
db_unread_char(int c)110d8404b7eSRyan Libby db_unread_char(int c)
1115b81b6b3SRodney W. Grimes {
112d8404b7eSRyan Libby
113d8404b7eSRyan Libby if (c == -1) {
114d8404b7eSRyan Libby /* Unread EOL at EOL is okay. */
115d8404b7eSRyan Libby if (db_lp < db_endlp)
116d8404b7eSRyan Libby db_error("db_unread_char(-1) before end of line\n");
117d8404b7eSRyan Libby } else {
118d8404b7eSRyan Libby if (db_lp > db_line) {
119d8404b7eSRyan Libby db_lp--;
120d8404b7eSRyan Libby if (*db_lp != c)
121d8404b7eSRyan Libby db_error("db_unread_char() wrong char\n");
122d8404b7eSRyan Libby } else {
123d8404b7eSRyan Libby db_error("db_unread_char() at beginning of line\n");
124d8404b7eSRyan Libby }
125d8404b7eSRyan Libby }
1265b81b6b3SRodney W. Grimes }
1275b81b6b3SRodney W. Grimes
128f73a856dSPoul-Henning Kamp static int db_look_token = 0;
1295b81b6b3SRodney W. Grimes
1305b81b6b3SRodney W. Grimes void
db_unread_token(int t)131e0c5dd43SConrad Meyer db_unread_token(int t)
1325b81b6b3SRodney W. Grimes {
1335b81b6b3SRodney W. Grimes db_look_token = t;
1345b81b6b3SRodney W. Grimes }
1355b81b6b3SRodney W. Grimes
1365b81b6b3SRodney W. Grimes int
db_read_token_flags(int flags)137e0c5dd43SConrad Meyer db_read_token_flags(int flags)
1385b81b6b3SRodney W. Grimes {
1395b81b6b3SRodney W. Grimes int t;
1405b81b6b3SRodney W. Grimes
141e0c5dd43SConrad Meyer MPASS((flags & ~(DRT_VALID_FLAGS_MASK)) == 0);
142e0c5dd43SConrad Meyer
1435b81b6b3SRodney W. Grimes if (db_look_token) {
1445b81b6b3SRodney W. Grimes t = db_look_token;
1455b81b6b3SRodney W. Grimes db_look_token = 0;
1465b81b6b3SRodney W. Grimes }
1475b81b6b3SRodney W. Grimes else
148e0c5dd43SConrad Meyer t = db_lex(flags);
1495b81b6b3SRodney W. Grimes return (t);
1505b81b6b3SRodney W. Grimes }
1515b81b6b3SRodney W. Grimes
1523da6ef3cSBruce Evans db_expr_t db_tok_number;
1535b81b6b3SRodney W. Grimes char db_tok_string[TOK_STRING_SIZE];
1545b81b6b3SRodney W. Grimes
1553da6ef3cSBruce Evans db_expr_t db_radix = 16;
1565b81b6b3SRodney W. Grimes
1575b81b6b3SRodney W. Grimes void
db_flush_lex(void)158a41dd031SPedro F. Giffuni db_flush_lex(void)
1595b81b6b3SRodney W. Grimes {
1605b81b6b3SRodney W. Grimes db_flush_line();
1615b81b6b3SRodney W. Grimes db_look_token = 0;
1625b81b6b3SRodney W. Grimes }
1635b81b6b3SRodney W. Grimes
164f23b4c91SGarrett Wollman static int
db_lex(int flags)165e0c5dd43SConrad Meyer db_lex(int flags)
1665b81b6b3SRodney W. Grimes {
167e0c5dd43SConrad Meyer int c, n, radix_mode;
16825b3370cSConrad Meyer bool lex_wspace, lex_hex_numbers;
169e0c5dd43SConrad Meyer
170e0c5dd43SConrad Meyer switch (flags & DRT_RADIX_MASK) {
171e0c5dd43SConrad Meyer case DRT_DEFAULT_RADIX:
172e0c5dd43SConrad Meyer radix_mode = -1;
173e0c5dd43SConrad Meyer break;
174e0c5dd43SConrad Meyer case DRT_OCTAL:
175e0c5dd43SConrad Meyer radix_mode = 8;
176e0c5dd43SConrad Meyer break;
177e0c5dd43SConrad Meyer case DRT_DECIMAL:
178e0c5dd43SConrad Meyer radix_mode = 10;
179e0c5dd43SConrad Meyer break;
180e0c5dd43SConrad Meyer case DRT_HEXADECIMAL:
181e0c5dd43SConrad Meyer radix_mode = 16;
182e0c5dd43SConrad Meyer break;
183e0c5dd43SConrad Meyer }
184e0c5dd43SConrad Meyer
185e0c5dd43SConrad Meyer lex_wspace = ((flags & DRT_WSPACE) != 0);
18625b3370cSConrad Meyer lex_hex_numbers = ((flags & DRT_HEX) != 0);
1875b81b6b3SRodney W. Grimes
1885b81b6b3SRodney W. Grimes c = db_read_char();
189e0c5dd43SConrad Meyer for (n = 0; c <= ' ' || c > '~'; n++) {
1905b81b6b3SRodney W. Grimes if (c == '\n' || c == -1)
1915b81b6b3SRodney W. Grimes return (tEOL);
1925b81b6b3SRodney W. Grimes c = db_read_char();
1935b81b6b3SRodney W. Grimes }
194e0c5dd43SConrad Meyer if (lex_wspace && n != 0) {
195e0c5dd43SConrad Meyer db_unread_char(c);
196e0c5dd43SConrad Meyer return (tWSPACE);
197e0c5dd43SConrad Meyer }
1985b81b6b3SRodney W. Grimes
19925b3370cSConrad Meyer if ((c >= '0' && c <= '9') ||
20025b3370cSConrad Meyer (lex_hex_numbers &&
20125b3370cSConrad Meyer ((c >= 'a' && c <= 'f') ||
20225b3370cSConrad Meyer (c >= 'A' && c <= 'F')))) {
2035b81b6b3SRodney W. Grimes /* number */
204381fe1aaSGarrett Wollman int r, digit = 0;
2055b81b6b3SRodney W. Grimes
206e0c5dd43SConrad Meyer if (radix_mode != -1)
207e0c5dd43SConrad Meyer r = radix_mode;
20825b3370cSConrad Meyer else if (c != '0')
2095b81b6b3SRodney W. Grimes r = db_radix;
2105b81b6b3SRodney W. Grimes else {
2115b81b6b3SRodney W. Grimes c = db_read_char();
2125b81b6b3SRodney W. Grimes if (c == 'O' || c == 'o')
2135b81b6b3SRodney W. Grimes r = 8;
2145b81b6b3SRodney W. Grimes else if (c == 'T' || c == 't')
2155b81b6b3SRodney W. Grimes r = 10;
2165b81b6b3SRodney W. Grimes else if (c == 'X' || c == 'x')
2175b81b6b3SRodney W. Grimes r = 16;
2185b81b6b3SRodney W. Grimes else {
2195b81b6b3SRodney W. Grimes r = db_radix;
2205b81b6b3SRodney W. Grimes db_unread_char(c);
2215b81b6b3SRodney W. Grimes }
2225b81b6b3SRodney W. Grimes c = db_read_char();
2235b81b6b3SRodney W. Grimes }
2245b81b6b3SRodney W. Grimes db_tok_number = 0;
2255b81b6b3SRodney W. Grimes for (;;) {
2265b81b6b3SRodney W. Grimes if (c >= '0' && c <= ((r == 8) ? '7' : '9'))
2275b81b6b3SRodney W. Grimes digit = c - '0';
2285b81b6b3SRodney W. Grimes else if (r == 16 && ((c >= 'A' && c <= 'F') ||
2295b81b6b3SRodney W. Grimes (c >= 'a' && c <= 'f'))) {
2305b81b6b3SRodney W. Grimes if (c >= 'a')
2315b81b6b3SRodney W. Grimes digit = c - 'a' + 10;
2325b81b6b3SRodney W. Grimes else if (c >= 'A')
2335b81b6b3SRodney W. Grimes digit = c - 'A' + 10;
2345b81b6b3SRodney W. Grimes }
2355b81b6b3SRodney W. Grimes else
2365b81b6b3SRodney W. Grimes break;
2375b81b6b3SRodney W. Grimes db_tok_number = db_tok_number * r + digit;
2385b81b6b3SRodney W. Grimes c = db_read_char();
2395b81b6b3SRodney W. Grimes }
2405b81b6b3SRodney W. Grimes if ((c >= '0' && c <= '9') ||
2415b81b6b3SRodney W. Grimes (c >= 'A' && c <= 'Z') ||
2425b81b6b3SRodney W. Grimes (c >= 'a' && c <= 'z') ||
2435b81b6b3SRodney W. Grimes (c == '_'))
2445b81b6b3SRodney W. Grimes {
2455b81b6b3SRodney W. Grimes db_error("Bad character in number\n");
2465b81b6b3SRodney W. Grimes db_flush_lex();
2475b81b6b3SRodney W. Grimes return (tEOF);
2485b81b6b3SRodney W. Grimes }
2495b81b6b3SRodney W. Grimes db_unread_char(c);
2505b81b6b3SRodney W. Grimes return (tNUMBER);
2515b81b6b3SRodney W. Grimes }
2525b81b6b3SRodney W. Grimes if ((c >= 'A' && c <= 'Z') ||
2535b81b6b3SRodney W. Grimes (c >= 'a' && c <= 'z') ||
2545b81b6b3SRodney W. Grimes c == '_' || c == '\\')
2555b81b6b3SRodney W. Grimes {
2565b81b6b3SRodney W. Grimes /* string */
2575b81b6b3SRodney W. Grimes char *cp;
2585b81b6b3SRodney W. Grimes
2595b81b6b3SRodney W. Grimes cp = db_tok_string;
2605b81b6b3SRodney W. Grimes if (c == '\\') {
2615b81b6b3SRodney W. Grimes c = db_read_char();
2625b81b6b3SRodney W. Grimes if (c == '\n' || c == -1)
2635b81b6b3SRodney W. Grimes db_error("Bad escape\n");
2645b81b6b3SRodney W. Grimes }
2655b81b6b3SRodney W. Grimes *cp++ = c;
2665b81b6b3SRodney W. Grimes while (1) {
2675b81b6b3SRodney W. Grimes c = db_read_char();
2685b81b6b3SRodney W. Grimes if ((c >= 'A' && c <= 'Z') ||
2695b81b6b3SRodney W. Grimes (c >= 'a' && c <= 'z') ||
2705b81b6b3SRodney W. Grimes (c >= '0' && c <= '9') ||
271a094749dSDoug Rabson c == '_' || c == '\\' || c == ':' || c == '.')
2725b81b6b3SRodney W. Grimes {
2735b81b6b3SRodney W. Grimes if (c == '\\') {
2745b81b6b3SRodney W. Grimes c = db_read_char();
2755b81b6b3SRodney W. Grimes if (c == '\n' || c == -1)
2765b81b6b3SRodney W. Grimes db_error("Bad escape\n");
2775b81b6b3SRodney W. Grimes }
2785b81b6b3SRodney W. Grimes *cp++ = c;
2795b81b6b3SRodney W. Grimes if (cp == db_tok_string+sizeof(db_tok_string)) {
2805b81b6b3SRodney W. Grimes db_error("String too long\n");
2815b81b6b3SRodney W. Grimes db_flush_lex();
2825b81b6b3SRodney W. Grimes return (tEOF);
2835b81b6b3SRodney W. Grimes }
2845b81b6b3SRodney W. Grimes continue;
2855b81b6b3SRodney W. Grimes }
2865b81b6b3SRodney W. Grimes else {
2875b81b6b3SRodney W. Grimes *cp = '\0';
2885b81b6b3SRodney W. Grimes break;
2895b81b6b3SRodney W. Grimes }
2905b81b6b3SRodney W. Grimes }
2915b81b6b3SRodney W. Grimes db_unread_char(c);
2925b81b6b3SRodney W. Grimes return (tIDENT);
2935b81b6b3SRodney W. Grimes }
2945b81b6b3SRodney W. Grimes
2955b81b6b3SRodney W. Grimes switch (c) {
2965b81b6b3SRodney W. Grimes case '+':
2975b81b6b3SRodney W. Grimes return (tPLUS);
2985b81b6b3SRodney W. Grimes case '-':
2995b81b6b3SRodney W. Grimes return (tMINUS);
3005b81b6b3SRodney W. Grimes case '.':
3015b81b6b3SRodney W. Grimes c = db_read_char();
3025b81b6b3SRodney W. Grimes if (c == '.')
3035b81b6b3SRodney W. Grimes return (tDOTDOT);
3045b81b6b3SRodney W. Grimes db_unread_char(c);
3055b81b6b3SRodney W. Grimes return (tDOT);
3065b81b6b3SRodney W. Grimes case '*':
3075b81b6b3SRodney W. Grimes return (tSTAR);
3085b81b6b3SRodney W. Grimes case '/':
3095b81b6b3SRodney W. Grimes return (tSLASH);
3105b81b6b3SRodney W. Grimes case '=':
311c69cee69SPedro F. Giffuni c = db_read_char();
312c69cee69SPedro F. Giffuni if (c == '=')
313c69cee69SPedro F. Giffuni return (tLOG_EQ);
314c69cee69SPedro F. Giffuni db_unread_char(c);
3155b81b6b3SRodney W. Grimes return (tEQ);
3165b81b6b3SRodney W. Grimes case '%':
3175b81b6b3SRodney W. Grimes return (tPCT);
3185b81b6b3SRodney W. Grimes case '#':
3195b81b6b3SRodney W. Grimes return (tHASH);
3205b81b6b3SRodney W. Grimes case '(':
3215b81b6b3SRodney W. Grimes return (tLPAREN);
3225b81b6b3SRodney W. Grimes case ')':
3235b81b6b3SRodney W. Grimes return (tRPAREN);
3245b81b6b3SRodney W. Grimes case ',':
3255b81b6b3SRodney W. Grimes return (tCOMMA);
3265b81b6b3SRodney W. Grimes case '"':
3275b81b6b3SRodney W. Grimes return (tDITTO);
3285b81b6b3SRodney W. Grimes case '$':
3295b81b6b3SRodney W. Grimes return (tDOLLAR);
3305b81b6b3SRodney W. Grimes case '!':
331c69cee69SPedro F. Giffuni c = db_read_char();
332c69cee69SPedro F. Giffuni if (c == '='){
333c69cee69SPedro F. Giffuni return (tLOG_NOT_EQ);
334c69cee69SPedro F. Giffuni }
335c69cee69SPedro F. Giffuni db_unread_char(c);
3365b81b6b3SRodney W. Grimes return (tEXCL);
33725b3370cSConrad Meyer case ':':
33825b3370cSConrad Meyer c = db_read_char();
33925b3370cSConrad Meyer if (c == ':')
34025b3370cSConrad Meyer return (tCOLONCOLON);
34125b3370cSConrad Meyer db_unread_char(c);
34225b3370cSConrad Meyer return (tCOLON);
343c9b0cc3bSRobert Watson case ';':
344c9b0cc3bSRobert Watson return (tSEMI);
345c69cee69SPedro F. Giffuni case '&':
346c69cee69SPedro F. Giffuni c = db_read_char();
347c69cee69SPedro F. Giffuni if (c == '&')
348c69cee69SPedro F. Giffuni return (tLOG_AND);
349c69cee69SPedro F. Giffuni db_unread_char(c);
350c69cee69SPedro F. Giffuni return (tBIT_AND);
351c69cee69SPedro F. Giffuni case '|':
352c69cee69SPedro F. Giffuni c = db_read_char();
353c69cee69SPedro F. Giffuni if (c == '|')
354c69cee69SPedro F. Giffuni return (tLOG_OR);
355c69cee69SPedro F. Giffuni db_unread_char(c);
356c69cee69SPedro F. Giffuni return (tBIT_OR);
3575b81b6b3SRodney W. Grimes case '<':
3585b81b6b3SRodney W. Grimes c = db_read_char();
3595b81b6b3SRodney W. Grimes if (c == '<')
3605b81b6b3SRodney W. Grimes return (tSHIFT_L);
361c69cee69SPedro F. Giffuni if (c == '=')
362c69cee69SPedro F. Giffuni return (tLESS_EQ);
3635b81b6b3SRodney W. Grimes db_unread_char(c);
364c69cee69SPedro F. Giffuni return (tLESS);
3655b81b6b3SRodney W. Grimes case '>':
3665b81b6b3SRodney W. Grimes c = db_read_char();
3675b81b6b3SRodney W. Grimes if (c == '>')
3685b81b6b3SRodney W. Grimes return (tSHIFT_R);
369c69cee69SPedro F. Giffuni if (c == '=')
370c69cee69SPedro F. Giffuni return (tGREATER_EQ);
3715b81b6b3SRodney W. Grimes db_unread_char(c);
372c69cee69SPedro F. Giffuni return (tGREATER);
373c69cee69SPedro F. Giffuni case '?':
374c69cee69SPedro F. Giffuni return (tQUESTION);
375c69cee69SPedro F. Giffuni case '~':
376c69cee69SPedro F. Giffuni return (tBIT_NOT);
3775b81b6b3SRodney W. Grimes case -1:
3785b81b6b3SRodney W. Grimes return (tEOF);
3795b81b6b3SRodney W. Grimes }
3805b81b6b3SRodney W. Grimes db_printf("Bad character\n");
3815b81b6b3SRodney W. Grimes db_flush_lex();
3825b81b6b3SRodney W. Grimes return (tEOF);
3835b81b6b3SRodney W. Grimes }
384