1 /* $OpenBSD: db_lex.c,v 1.4 1996/04/21 22:19:03 deraadt Exp $ */ 2 /* $NetBSD: db_lex.c,v 1.8 1996/02/05 01:57:05 christos Exp $ */ 3 4 /* 5 * Mach Operating System 6 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University 7 * All Rights Reserved. 8 * 9 * Permission to use, copy, modify and distribute this software and its 10 * documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 17 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie Mellon 27 * the rights to redistribute these changes. 28 * 29 * Author: David B. Golub, Carnegie Mellon University 30 * Date: 7/90 31 */ 32 33 /* 34 * Lexical analyzer. 35 */ 36 #include <sys/param.h> 37 #include <sys/proc.h> 38 39 #include <machine/db_machdep.h> 40 41 #include <ddb/db_lex.h> 42 #include <ddb/db_output.h> 43 #include <ddb/db_command.h> 44 #include <ddb/db_sym.h> 45 #include <ddb/db_extern.h> 46 47 char db_line[120]; 48 char * db_lp, *db_endlp; 49 50 int 51 db_read_line() 52 { 53 int i; 54 55 i = db_readline(db_line, sizeof(db_line)); 56 if (i == 0) 57 return (0); /* EOI */ 58 db_lp = db_line; 59 db_endlp = db_lp + i; 60 return (i); 61 } 62 63 void 64 db_flush_line() 65 { 66 db_lp = db_line; 67 db_endlp = db_line; 68 } 69 70 int db_look_char = 0; 71 72 int 73 db_read_char() 74 { 75 int c; 76 77 if (db_look_char != 0) { 78 c = db_look_char; 79 db_look_char = 0; 80 } 81 else if (db_lp >= db_endlp) 82 c = -1; 83 else 84 c = *db_lp++; 85 return (c); 86 } 87 88 void 89 db_unread_char(c) 90 int c; 91 { 92 db_look_char = c; 93 } 94 95 int db_look_token = 0; 96 97 void 98 db_unread_token(t) 99 int t; 100 { 101 db_look_token = t; 102 } 103 104 int 105 db_read_token() 106 { 107 int t; 108 109 if (db_look_token) { 110 t = db_look_token; 111 db_look_token = 0; 112 } 113 else 114 t = db_lex(); 115 return (t); 116 } 117 118 int db_radix = 16; 119 120 void 121 db_flush_lex() 122 { 123 db_flush_line(); 124 db_look_char = 0; 125 db_look_token = 0; 126 } 127 128 int 129 db_lex() 130 { 131 int c; 132 133 c = db_read_char(); 134 while (c <= ' ' || c > '~') { 135 if (c == '\n' || c == -1) 136 return (tEOL); 137 c = db_read_char(); 138 } 139 140 if (c >= '0' && c <= '9') { 141 /* number */ 142 int r, digit = 0; 143 144 if (c > '0') 145 r = db_radix; 146 else { 147 c = db_read_char(); 148 if (c == 'O' || c == 'o') 149 r = 8; 150 else if (c == 'T' || c == 't') 151 r = 10; 152 else if (c == 'X' || c == 'x') 153 r = 16; 154 else { 155 r = db_radix; 156 db_unread_char(c); 157 } 158 c = db_read_char(); 159 } 160 db_tok_number = 0; 161 for (;;) { 162 if (c >= '0' && c <= ((r == 8) ? '7' : '9')) 163 digit = c - '0'; 164 else if (r == 16 && ((c >= 'A' && c <= 'F') || 165 (c >= 'a' && c <= 'f'))) { 166 if (c >= 'a') 167 digit = c - 'a' + 10; 168 else if (c >= 'A') 169 digit = c - 'A' + 10; 170 } 171 else 172 break; 173 db_tok_number = db_tok_number * r + digit; 174 c = db_read_char(); 175 } 176 if ((c >= '0' && c <= '9') || 177 (c >= 'A' && c <= 'Z') || 178 (c >= 'a' && c <= 'z') || 179 (c == '_')) 180 { 181 db_error("Bad character in number\n"); 182 /*NOTREACHED*/ 183 } 184 db_unread_char(c); 185 return (tNUMBER); 186 } 187 if ((c >= 'A' && c <= 'Z') || 188 (c >= 'a' && c <= 'z') || 189 c == '_' || c == '\\') 190 { 191 /* string */ 192 char *cp; 193 194 cp = db_tok_string; 195 if (c == '\\') { 196 c = db_read_char(); 197 if (c == '\n' || c == -1) { 198 db_error("Bad escape\n"); 199 /*NOTREACHED*/ 200 } 201 } 202 *cp++ = c; 203 while (1) { 204 c = db_read_char(); 205 if ((c >= 'A' && c <= 'Z') || 206 (c >= 'a' && c <= 'z') || 207 (c >= '0' && c <= '9') || 208 c == '_' || c == '\\' || c == ':') 209 { 210 if (c == '\\') { 211 c = db_read_char(); 212 if (c == '\n' || c == -1) { 213 db_error("Bad escape\n"); 214 /*NOTREACHED*/ 215 } 216 } 217 *cp++ = c; 218 if (cp == db_tok_string+sizeof(db_tok_string)) { 219 db_error("String too long\n"); 220 /*NOTREACHED*/ 221 } 222 continue; 223 } 224 else { 225 *cp = '\0'; 226 break; 227 } 228 } 229 db_unread_char(c); 230 return (tIDENT); 231 } 232 233 switch (c) { 234 case '+': 235 return (tPLUS); 236 case '-': 237 return (tMINUS); 238 case '.': 239 c = db_read_char(); 240 if (c == '.') 241 return (tDOTDOT); 242 db_unread_char(c); 243 return (tDOT); 244 case '*': 245 return (tSTAR); 246 case '/': 247 return (tSLASH); 248 case '=': 249 return (tEQ); 250 case '%': 251 return (tPCT); 252 case '#': 253 return (tHASH); 254 case '(': 255 return (tLPAREN); 256 case ')': 257 return (tRPAREN); 258 case ',': 259 return (tCOMMA); 260 case '"': 261 return (tDITTO); 262 case '$': 263 return (tDOLLAR); 264 case '!': 265 return (tEXCL); 266 case '<': 267 c = db_read_char(); 268 if (c == '<') 269 return (tSHIFT_L); 270 db_unread_char(c); 271 break; 272 case '>': 273 c = db_read_char(); 274 if (c == '>') 275 return (tSHIFT_R); 276 db_unread_char(c); 277 break; 278 case -1: 279 return (tEOF); 280 } 281 db_printf("Bad character\n"); 282 db_flush_lex(); 283 return (tEOF); 284 } 285