1 /* 2 * Mach Operating System 3 * Copyright (c) 1991,1990 Carnegie Mellon University 4 * All Rights Reserved. 5 * 6 * Permission to use, copy, modify and distribute this software and its 7 * documentation is hereby granted, provided that both the copyright 8 * notice and this permission notice appear in all copies of the 9 * software, derivative works or modified versions, and any portions 10 * thereof, and that both notices appear in supporting documentation. 11 * 12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 15 * 16 * Carnegie Mellon requests users of this software to return to 17 * 18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 19 * School of Computer Science 20 * Carnegie Mellon University 21 * Pittsburgh PA 15213-3890 22 * 23 * any improvements or extensions that they make and grant Carnegie the 24 * rights to redistribute these changes. 25 * 26 * $FreeBSD: src/sys/ddb/db_lex.c,v 1.18 1999/08/28 00:41:08 peter Exp $ 27 * $DragonFly: src/sys/ddb/db_lex.c,v 1.5 2005/12/23 21:35:44 swildner Exp $ 28 */ 29 30 /* 31 * Author: David B. Golub, Carnegie Mellon University 32 * Date: 7/90 33 */ 34 /* 35 * Lexical analyzer. 36 */ 37 #include <sys/param.h> 38 39 #include <ddb/ddb.h> 40 #include <ddb/db_lex.h> 41 42 static char db_line[120]; 43 static char * db_lp, *db_endlp; 44 45 static int db_lex (void); 46 static void db_flush_line (void); 47 static int db_read_char (void); 48 static void db_unread_char (int); 49 50 int 51 db_read_line(void) 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 static void 64 db_flush_line(void) 65 { 66 db_lp = db_line; 67 db_endlp = db_line; 68 } 69 70 static int db_look_char = 0; 71 72 static int 73 db_read_char(void) 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 static void 89 db_unread_char(int c) 90 { 91 db_look_char = c; 92 } 93 94 static int db_look_token = 0; 95 96 void 97 db_unread_token(int t) 98 { 99 db_look_token = t; 100 } 101 102 int 103 db_read_token(void) 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 db_expr_t db_tok_number; 117 char db_tok_string[TOK_STRING_SIZE]; 118 119 db_expr_t db_radix = 16; 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 static 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 db_flush_lex(); 184 return (tEOF); 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 } 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 } 215 *cp++ = c; 216 if (cp == db_tok_string+sizeof(db_tok_string)) { 217 db_error("String too long\n"); 218 db_flush_lex(); 219 return (tEOF); 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