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