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