xref: /freebsd/sys/ddb/db_lex.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
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