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.4 1994/08/13 03:49:20 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 static int db_lex(void); 45 46 int 47 db_read_line() 48 { 49 int i; 50 51 i = db_readline(db_line, sizeof(db_line)); 52 if (i == 0) 53 return (0); /* EOI */ 54 db_lp = db_line; 55 db_endlp = db_lp + i; 56 return (i); 57 } 58 59 void 60 db_flush_line() 61 { 62 db_lp = db_line; 63 db_endlp = db_line; 64 } 65 66 int db_look_char = 0; 67 68 int 69 db_read_char() 70 { 71 int c; 72 73 if (db_look_char != 0) { 74 c = db_look_char; 75 db_look_char = 0; 76 } 77 else if (db_lp >= db_endlp) 78 c = -1; 79 else 80 c = *db_lp++; 81 return (c); 82 } 83 84 void 85 db_unread_char(c) 86 int c; 87 { 88 db_look_char = c; 89 } 90 91 int db_look_token = 0; 92 93 void 94 db_unread_token(t) 95 int t; 96 { 97 db_look_token = t; 98 } 99 100 int 101 db_read_token() 102 { 103 int t; 104 105 if (db_look_token) { 106 t = db_look_token; 107 db_look_token = 0; 108 } 109 else 110 t = db_lex(); 111 return (t); 112 } 113 114 int db_tok_number; 115 char db_tok_string[TOK_STRING_SIZE]; 116 117 int db_radix = 16; 118 119 void 120 db_flush_lex() 121 { 122 db_flush_line(); 123 db_look_char = 0; 124 db_look_token = 0; 125 } 126 127 static int 128 db_lex() 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 db_flush_lex(); 182 return (tEOF); 183 } 184 db_unread_char(c); 185 return (tNUMBER); 186 } 187 if ((c >= 'A' && c <= 'Z') || 188 (c >= 'a' && c <= 'z') || 189 c == '_' || c == '\\') 190 { 191 /* string */ 192 char *cp; 193 194 cp = db_tok_string; 195 if (c == '\\') { 196 c = db_read_char(); 197 if (c == '\n' || c == -1) 198 db_error("Bad escape\n"); 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 } 213 *cp++ = c; 214 if (cp == db_tok_string+sizeof(db_tok_string)) { 215 db_error("String too long\n"); 216 db_flush_lex(); 217 return (tEOF); 218 } 219 continue; 220 } 221 else { 222 *cp = '\0'; 223 break; 224 } 225 } 226 db_unread_char(c); 227 return (tIDENT); 228 } 229 230 switch (c) { 231 case '+': 232 return (tPLUS); 233 case '-': 234 return (tMINUS); 235 case '.': 236 c = db_read_char(); 237 if (c == '.') 238 return (tDOTDOT); 239 db_unread_char(c); 240 return (tDOT); 241 case '*': 242 return (tSTAR); 243 case '/': 244 return (tSLASH); 245 case '=': 246 return (tEQ); 247 case '%': 248 return (tPCT); 249 case '#': 250 return (tHASH); 251 case '(': 252 return (tLPAREN); 253 case ')': 254 return (tRPAREN); 255 case ',': 256 return (tCOMMA); 257 case '"': 258 return (tDITTO); 259 case '$': 260 return (tDOLLAR); 261 case '!': 262 return (tEXCL); 263 case '<': 264 c = db_read_char(); 265 if (c == '<') 266 return (tSHIFT_L); 267 db_unread_char(c); 268 break; 269 case '>': 270 c = db_read_char(); 271 if (c == '>') 272 return (tSHIFT_R); 273 db_unread_char(c); 274 break; 275 case -1: 276 return (tEOF); 277 } 278 db_printf("Bad character\n"); 279 db_flush_lex(); 280 return (tEOF); 281 } 282