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