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