1 /* $OpenBSD: db_lex.c,v 1.9 2006/03/13 06:23:20 jsg 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 <uvm/uvm_extern.h> 40 41 #include <machine/db_machdep.h> 42 43 #include <ddb/db_lex.h> 44 #include <ddb/db_output.h> 45 #include <ddb/db_command.h> 46 #include <ddb/db_sym.h> 47 #include <ddb/db_extern.h> 48 #include <ddb/db_var.h> 49 50 char db_line[120]; 51 char * db_lp, *db_endlp; 52 53 db_expr_t db_tok_number; 54 char db_tok_string[TOK_STRING_SIZE]; 55 56 int 57 db_read_line(void) 58 { 59 int i; 60 61 i = db_readline(db_line, sizeof(db_line)); 62 if (i == 0) 63 return (0); /* EOI */ 64 db_lp = db_line; 65 db_endlp = db_lp + i; 66 return (i); 67 } 68 69 void 70 db_flush_line(void) 71 { 72 db_lp = db_line; 73 db_endlp = db_line; 74 } 75 76 int db_look_char = 0; 77 78 int 79 db_read_char(void) 80 { 81 int c; 82 83 if (db_look_char != 0) { 84 c = db_look_char; 85 db_look_char = 0; 86 } 87 else if (db_lp >= db_endlp) 88 c = -1; 89 else 90 c = *db_lp++; 91 return (c); 92 } 93 94 void 95 db_unread_char(int c) 96 { 97 db_look_char = c; 98 } 99 100 int db_look_token = 0; 101 102 void 103 db_unread_token(int t) 104 { 105 db_look_token = t; 106 } 107 108 int 109 db_read_token(void) 110 { 111 int t; 112 113 if (db_look_token) { 114 t = db_look_token; 115 db_look_token = 0; 116 } 117 else 118 t = db_lex(); 119 return (t); 120 } 121 122 void 123 db_flush_lex(void) 124 { 125 db_flush_line(); 126 db_look_char = 0; 127 db_look_token = 0; 128 } 129 130 int 131 db_lex(void) 132 { 133 int c; 134 135 c = db_read_char(); 136 while (c <= ' ' || c > '~') { 137 if (c == '\n' || c == -1) 138 return (tEOL); 139 c = db_read_char(); 140 } 141 142 if (c >= '0' && c <= '9') { 143 /* number */ 144 int r, digit = 0; 145 146 if (c > '0') 147 r = db_radix; 148 else { 149 c = db_read_char(); 150 if (c == 'O' || c == 'o') 151 r = 8; 152 else if (c == 'T' || c == 't') 153 r = 10; 154 else if (c == 'X' || c == 'x') 155 r = 16; 156 else { 157 r = db_radix; 158 db_unread_char(c); 159 } 160 c = db_read_char(); 161 } 162 db_tok_number = 0; 163 for (;;) { 164 if (c >= '0' && c <= ((r == 8) ? '7' : '9')) 165 digit = c - '0'; 166 else if (r == 16 && ((c >= 'A' && c <= 'F') || 167 (c >= 'a' && c <= 'f'))) { 168 if (c >= 'a') 169 digit = c - 'a' + 10; 170 else if (c >= 'A') 171 digit = c - 'A' + 10; 172 } 173 else 174 break; 175 db_tok_number = db_tok_number * r + digit; 176 c = db_read_char(); 177 } 178 if ((c >= '0' && c <= '9') || 179 (c >= 'A' && c <= 'Z') || 180 (c >= 'a' && c <= 'z') || 181 (c == '_')) 182 { 183 db_error("Bad character in number\n"); 184 /*NOTREACHED*/ 185 } 186 db_unread_char(c); 187 return (tNUMBER); 188 } 189 if ((c >= 'A' && c <= 'Z') || 190 (c >= 'a' && c <= 'z') || 191 c == '_' || c == '\\') 192 { 193 /* string */ 194 char *cp; 195 196 cp = db_tok_string; 197 if (c == '\\') { 198 c = db_read_char(); 199 if (c == '\n' || c == -1) { 200 db_error("Bad escape\n"); 201 /*NOTREACHED*/ 202 } 203 } 204 *cp++ = c; 205 while (1) { 206 c = db_read_char(); 207 if ((c >= 'A' && c <= 'Z') || 208 (c >= 'a' && c <= 'z') || 209 (c >= '0' && c <= '9') || 210 c == '_' || c == '\\' || c == ':') 211 { 212 if (c == '\\') { 213 c = db_read_char(); 214 if (c == '\n' || c == -1) { 215 db_error("Bad escape\n"); 216 /*NOTREACHED*/ 217 } 218 } 219 *cp++ = c; 220 if (cp == db_tok_string+sizeof(db_tok_string)) { 221 db_error("String too long\n"); 222 /*NOTREACHED*/ 223 } 224 continue; 225 } 226 else { 227 *cp = '\0'; 228 break; 229 } 230 } 231 db_unread_char(c); 232 return (tIDENT); 233 } 234 235 switch (c) { 236 case '+': 237 return (tPLUS); 238 case '-': 239 return (tMINUS); 240 case '.': 241 c = db_read_char(); 242 if (c == '.') 243 return (tDOTDOT); 244 db_unread_char(c); 245 return (tDOT); 246 case '*': 247 return (tSTAR); 248 case '/': 249 return (tSLASH); 250 case '=': 251 return (tEQ); 252 case '%': 253 return (tPCT); 254 case '#': 255 return (tHASH); 256 case '(': 257 return (tLPAREN); 258 case ')': 259 return (tRPAREN); 260 case ',': 261 return (tCOMMA); 262 case '"': 263 return (tDITTO); 264 case '$': 265 return (tDOLLAR); 266 case '!': 267 return (tEXCL); 268 case '<': 269 c = db_read_char(); 270 if (c == '<') 271 return (tSHIFT_L); 272 db_unread_char(c); 273 break; 274 case '>': 275 c = db_read_char(); 276 if (c == '>') 277 return (tSHIFT_R); 278 db_unread_char(c); 279 break; 280 case -1: 281 return (tEOF); 282 } 283 db_printf("Bad character\n"); 284 db_flush_lex(); 285 return (tEOF); 286 } 287