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