db_lex.c revision 273265
12Sjlaskey/*- 26Sjlaskey * Mach Operating System 32Sjlaskey * Copyright (c) 1991,1990 Carnegie Mellon University 4877Sattila * All Rights Reserved. 52Sjlaskey * 62Sjlaskey * Permission to use, copy, modify and distribute this software and its 72Sjlaskey * documentation is hereby granted, provided that both the copyright 8877Sattila * notice and this permission notice appear in all copies of the 92Sjlaskey * software, derivative works or modified versions, and any portions 102Sjlaskey * thereof, and that both notices appear in supporting documentation. 112Sjlaskey * 122Sjlaskey * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 132Sjlaskey * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14877Sattila * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 152Sjlaskey * 162Sjlaskey * Carnegie Mellon requests users of this software to return to 172Sjlaskey * 18877Sattila * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 192Sjlaskey * School of Computer Science 202Sjlaskey * Carnegie Mellon University 212Sjlaskey * Pittsburgh PA 15213-3890 222Sjlaskey * 232Sjlaskey * any improvements or extensions that they make and grant Carnegie the 242Sjlaskey * rights to redistribute these changes. 252Sjlaskey */ 262Sjlaskey/* 272Sjlaskey * Author: David B. Golub, Carnegie Mellon University 282Sjlaskey * Date: 7/90 292Sjlaskey */ 302Sjlaskey/* 312Sjlaskey * Lexical analyzer. 322Sjlaskey */ 332Sjlaskey 342Sjlaskey#include <sys/cdefs.h> 352Sjlaskey__FBSDID("$FreeBSD: stable/10/sys/ddb/db_lex.c 273265 2014-10-18 19:22:59Z pfg $"); 362Sjlaskey 372Sjlaskey#include <sys/param.h> 382Sjlaskey#include <sys/libkern.h> 392Sjlaskey 402Sjlaskey#include <ddb/ddb.h> 412Sjlaskey#include <ddb/db_lex.h> 422Sjlaskey 432Sjlaskeystatic char db_line[DB_MAXLINE]; 442Sjlaskeystatic char * db_lp, *db_endlp; 452Sjlaskey 462Sjlaskeystatic int db_lex(void); 472Sjlaskeystatic void db_flush_line(void); 482Sjlaskeystatic int db_read_char(void); 492Sjlaskeystatic void db_unread_char(int); 50278Sattila 512Sjlaskeyint 522Sjlaskeydb_read_line(void) 532Sjlaskey{ 542Sjlaskey int i; 552Sjlaskey 562Sjlaskey i = db_readline(db_line, sizeof(db_line)); 572Sjlaskey if (i == 0) 582Sjlaskey return (0); /* EOI */ 592Sjlaskey db_lp = db_line; 602Sjlaskey db_endlp = db_lp + i; 612Sjlaskey return (i); 622Sjlaskey} 632Sjlaskey 642Sjlaskey/* 652Sjlaskey * Simulate a line of input into DDB. 66278Sattila */ 672Sjlaskeyvoid 682Sjlaskeydb_inject_line(const char *command) 692Sjlaskey{ 702Sjlaskey 712Sjlaskey strlcpy(db_line, command, sizeof(db_line)); 722Sjlaskey db_lp = db_line; 732Sjlaskey db_endlp = db_lp + strlen(command); 742Sjlaskey} 752Sjlaskey 762Sjlaskey/* 772Sjlaskey * In rare cases, we may want to pull the remainder of the line input 782Sjlaskey * verbatim, rather than lexing it. For example, when assigning literal 792Sjlaskey * values associated with scripts. In that case, return a static pointer to 802Sjlaskey * the current location in the input buffer. The caller must be aware that 81278Sattila * the contents are not stable if other lex/input calls are made. 822Sjlaskey */ 832Sjlaskeychar * 842Sjlaskeydb_get_line(void) 852Sjlaskey{ 862Sjlaskey 872Sjlaskey return (db_lp); 882Sjlaskey} 892Sjlaskey 902Sjlaskeystatic void 91278Sattiladb_flush_line() 922Sjlaskey{ 932Sjlaskey db_lp = db_line; 942Sjlaskey db_endlp = db_line; 952Sjlaskey} 962Sjlaskey 972Sjlaskeystatic int db_look_char = 0; 982Sjlaskey 992Sjlaskeystatic int 1002Sjlaskeydb_read_char(void) 1012Sjlaskey{ 1022Sjlaskey int c; 1032Sjlaskey 1042Sjlaskey if (db_look_char != 0) { 1052Sjlaskey c = db_look_char; 1062Sjlaskey db_look_char = 0; 107278Sattila } 1082Sjlaskey else if (db_lp >= db_endlp) 1092Sjlaskey c = -1; 1102Sjlaskey else 1112Sjlaskey c = *db_lp++; 1122Sjlaskey return (c); 1132Sjlaskey} 1142Sjlaskey 1152Sjlaskeystatic void 1162Sjlaskeydb_unread_char(c) 1172Sjlaskey int c; 1182Sjlaskey{ 1192Sjlaskey db_look_char = c; 1202Sjlaskey} 1212Sjlaskey 1222Sjlaskeystatic int db_look_token = 0; 1232Sjlaskey 1242Sjlaskeyvoid 1252Sjlaskeydb_unread_token(t) 1262Sjlaskey int t; 1272Sjlaskey{ 1282Sjlaskey db_look_token = t; 1292Sjlaskey} 1302Sjlaskey 1312Sjlaskeyint 1322Sjlaskeydb_read_token() 1332Sjlaskey{ 134278Sattila int t; 1352Sjlaskey 1362Sjlaskey if (db_look_token) { 1372Sjlaskey t = db_look_token; 1382Sjlaskey db_look_token = 0; 1392Sjlaskey } 1402Sjlaskey else 141278Sattila t = db_lex(); 1422Sjlaskey return (t); 1432Sjlaskey} 1442Sjlaskey 1452Sjlaskeydb_expr_t db_tok_number; 1462Sjlaskeychar db_tok_string[TOK_STRING_SIZE]; 1472Sjlaskey 1482Sjlaskeydb_expr_t db_radix = 16; 1492Sjlaskey 1502Sjlaskeyvoid 1512Sjlaskeydb_flush_lex(void) 1522Sjlaskey{ 1532Sjlaskey db_flush_line(); 1542Sjlaskey db_look_char = 0; 1552Sjlaskey db_look_token = 0; 1562Sjlaskey} 157278Sattila 158278Sattilastatic int 1592Sjlaskeydb_lex(void) 1602Sjlaskey{ 1612Sjlaskey int c; 1622Sjlaskey 1632Sjlaskey c = db_read_char(); 1642Sjlaskey while (c <= ' ' || c > '~') { 1652Sjlaskey if (c == '\n' || c == -1) 1662Sjlaskey return (tEOL); 167278Sattila c = db_read_char(); 1682Sjlaskey } 1692Sjlaskey 170278Sattila if (c >= '0' && c <= '9') { 1712Sjlaskey /* number */ 172278Sattila int r, digit = 0; 1732Sjlaskey 1742Sjlaskey if (c > '0') 1752Sjlaskey r = db_radix; 1762Sjlaskey else { 1772Sjlaskey c = db_read_char(); 1782Sjlaskey if (c == 'O' || c == 'o') 1792Sjlaskey r = 8; 1802Sjlaskey else if (c == 'T' || c == 't') 1812Sjlaskey r = 10; 1822Sjlaskey else if (c == 'X' || c == 'x') 1832Sjlaskey r = 16; 1842Sjlaskey else { 1852Sjlaskey r = db_radix; 1862Sjlaskey db_unread_char(c); 1872Sjlaskey } 1882Sjlaskey c = db_read_char(); 1892Sjlaskey } 1902Sjlaskey db_tok_number = 0; 1912Sjlaskey for (;;) { 1922Sjlaskey if (c >= '0' && c <= ((r == 8) ? '7' : '9')) 1932Sjlaskey digit = c - '0'; 1942Sjlaskey else if (r == 16 && ((c >= 'A' && c <= 'F') || 1952Sjlaskey (c >= 'a' && c <= 'f'))) { 1962Sjlaskey if (c >= 'a') 1972Sjlaskey digit = c - 'a' + 10; 1982Sjlaskey else if (c >= 'A') 1992Sjlaskey digit = c - 'A' + 10; 2002Sjlaskey } 2012Sjlaskey else 2022Sjlaskey break; 2032Sjlaskey db_tok_number = db_tok_number * r + digit; 2042Sjlaskey c = db_read_char(); 2052Sjlaskey } 2062Sjlaskey if ((c >= '0' && c <= '9') || 2072Sjlaskey (c >= 'A' && c <= 'Z') || 2082Sjlaskey (c >= 'a' && c <= 'z') || 2092Sjlaskey (c == '_')) 2102Sjlaskey { 2112Sjlaskey db_error("Bad character in number\n"); 2122Sjlaskey db_flush_lex(); 2132Sjlaskey return (tEOF); 2142Sjlaskey } 2152Sjlaskey db_unread_char(c); 2162Sjlaskey return (tNUMBER); 217 } 218 if ((c >= 'A' && c <= 'Z') || 219 (c >= 'a' && c <= 'z') || 220 c == '_' || c == '\\') 221 { 222 /* string */ 223 char *cp; 224 225 cp = db_tok_string; 226 if (c == '\\') { 227 c = db_read_char(); 228 if (c == '\n' || c == -1) 229 db_error("Bad escape\n"); 230 } 231 *cp++ = c; 232 while (1) { 233 c = db_read_char(); 234 if ((c >= 'A' && c <= 'Z') || 235 (c >= 'a' && c <= 'z') || 236 (c >= '0' && c <= '9') || 237 c == '_' || c == '\\' || c == ':' || c == '.') 238 { 239 if (c == '\\') { 240 c = db_read_char(); 241 if (c == '\n' || c == -1) 242 db_error("Bad escape\n"); 243 } 244 *cp++ = c; 245 if (cp == db_tok_string+sizeof(db_tok_string)) { 246 db_error("String too long\n"); 247 db_flush_lex(); 248 return (tEOF); 249 } 250 continue; 251 } 252 else { 253 *cp = '\0'; 254 break; 255 } 256 } 257 db_unread_char(c); 258 return (tIDENT); 259 } 260 261 switch (c) { 262 case '+': 263 return (tPLUS); 264 case '-': 265 return (tMINUS); 266 case '.': 267 c = db_read_char(); 268 if (c == '.') 269 return (tDOTDOT); 270 db_unread_char(c); 271 return (tDOT); 272 case '*': 273 return (tSTAR); 274 case '/': 275 return (tSLASH); 276 case '=': 277 return (tEQ); 278 case '%': 279 return (tPCT); 280 case '#': 281 return (tHASH); 282 case '(': 283 return (tLPAREN); 284 case ')': 285 return (tRPAREN); 286 case ',': 287 return (tCOMMA); 288 case '"': 289 return (tDITTO); 290 case '$': 291 return (tDOLLAR); 292 case '!': 293 return (tEXCL); 294 case ';': 295 return (tSEMI); 296 case '<': 297 c = db_read_char(); 298 if (c == '<') 299 return (tSHIFT_L); 300 db_unread_char(c); 301 break; 302 case '>': 303 c = db_read_char(); 304 if (c == '>') 305 return (tSHIFT_R); 306 db_unread_char(c); 307 break; 308 case -1: 309 return (tEOF); 310 } 311 db_printf("Bad character\n"); 312 db_flush_lex(); 313 return (tEOF); 314} 315