1139747Simp/*- 24Srgrimes * Mach Operating System 34Srgrimes * Copyright (c) 1991,1990 Carnegie Mellon University 44Srgrimes * All Rights Reserved. 58876Srgrimes * 64Srgrimes * Permission to use, copy, modify and distribute this software and its 74Srgrimes * documentation is hereby granted, provided that both the copyright 84Srgrimes * notice and this permission notice appear in all copies of the 94Srgrimes * software, derivative works or modified versions, and any portions 104Srgrimes * thereof, and that both notices appear in supporting documentation. 118876Srgrimes * 128876Srgrimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 134Srgrimes * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 144Srgrimes * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 158876Srgrimes * 164Srgrimes * Carnegie Mellon requests users of this software to return to 178876Srgrimes * 184Srgrimes * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 194Srgrimes * School of Computer Science 204Srgrimes * Carnegie Mellon University 214Srgrimes * Pittsburgh PA 15213-3890 228876Srgrimes * 234Srgrimes * any improvements or extensions that they make and grant Carnegie the 244Srgrimes * rights to redistribute these changes. 254Srgrimes */ 264Srgrimes/* 274Srgrimes * Author: David B. Golub, Carnegie Mellon University 284Srgrimes * Date: 7/90 294Srgrimes */ 304Srgrimes/* 314Srgrimes * Lexical analyzer. 324Srgrimes */ 33116176Sobrien 34116176Sobrien#include <sys/cdefs.h> 35116176Sobrien__FBSDID("$FreeBSD$"); 36116176Sobrien 372056Swollman#include <sys/param.h> 38174914Srwatson#include <sys/libkern.h> 3912734Sbde 402056Swollman#include <ddb/ddb.h> 414Srgrimes#include <ddb/db_lex.h> 424Srgrimes 43174914Srwatsonstatic char db_line[DB_MAXLINE]; 4412720Sphkstatic char * db_lp, *db_endlp; 454Srgrimes 4692756Salfredstatic int db_lex(void); 4792756Salfredstatic void db_flush_line(void); 4892756Salfredstatic int db_read_char(void); 4992756Salfredstatic void db_unread_char(int); 502112Swollman 514Srgrimesint 52273265Spfgdb_read_line(void) 534Srgrimes{ 544Srgrimes int i; 554Srgrimes 564Srgrimes i = db_readline(db_line, sizeof(db_line)); 574Srgrimes if (i == 0) 584Srgrimes return (0); /* EOI */ 594Srgrimes db_lp = db_line; 604Srgrimes db_endlp = db_lp + i; 614Srgrimes return (i); 624Srgrimes} 634Srgrimes 64174914Srwatson/* 65174914Srwatson * Simulate a line of input into DDB. 66174914Srwatson */ 67174914Srwatsonvoid 68174914Srwatsondb_inject_line(const char *command) 69174914Srwatson{ 70174914Srwatson 71174914Srwatson strlcpy(db_line, command, sizeof(db_line)); 72174914Srwatson db_lp = db_line; 73174914Srwatson db_endlp = db_lp + strlen(command); 74174914Srwatson} 75174914Srwatson 76174914Srwatson/* 77174914Srwatson * In rare cases, we may want to pull the remainder of the line input 78174914Srwatson * verbatim, rather than lexing it. For example, when assigning literal 79174914Srwatson * values associated with scripts. In that case, return a static pointer to 80174914Srwatson * the current location in the input buffer. The caller must be aware that 81174914Srwatson * the contents are not stable if other lex/input calls are made. 82174914Srwatson */ 83174914Srwatsonchar * 84174914Srwatsondb_get_line(void) 85174914Srwatson{ 86174914Srwatson 87174914Srwatson return (db_lp); 88174914Srwatson} 89174914Srwatson 9012515Sphkstatic void 914Srgrimesdb_flush_line() 924Srgrimes{ 934Srgrimes db_lp = db_line; 944Srgrimes db_endlp = db_line; 954Srgrimes} 964Srgrimes 9712515Sphkstatic int db_look_char = 0; 984Srgrimes 9912515Sphkstatic int 100273265Spfgdb_read_char(void) 1014Srgrimes{ 1024Srgrimes int c; 1034Srgrimes 1044Srgrimes if (db_look_char != 0) { 1054Srgrimes c = db_look_char; 1064Srgrimes db_look_char = 0; 1074Srgrimes } 1084Srgrimes else if (db_lp >= db_endlp) 1094Srgrimes c = -1; 1108876Srgrimes else 1114Srgrimes c = *db_lp++; 1124Srgrimes return (c); 1134Srgrimes} 1144Srgrimes 11512515Sphkstatic void 1164Srgrimesdb_unread_char(c) 117798Swollman int c; 1184Srgrimes{ 1194Srgrimes db_look_char = c; 1204Srgrimes} 1214Srgrimes 12212515Sphkstatic int db_look_token = 0; 1234Srgrimes 1244Srgrimesvoid 1254Srgrimesdb_unread_token(t) 1264Srgrimes int t; 1274Srgrimes{ 1284Srgrimes db_look_token = t; 1294Srgrimes} 1304Srgrimes 1314Srgrimesint 1324Srgrimesdb_read_token() 1334Srgrimes{ 1344Srgrimes int t; 1354Srgrimes 1364Srgrimes if (db_look_token) { 1374Srgrimes t = db_look_token; 1384Srgrimes db_look_token = 0; 1394Srgrimes } 1404Srgrimes else 1414Srgrimes t = db_lex(); 1424Srgrimes return (t); 1434Srgrimes} 1444Srgrimes 14537504Sbdedb_expr_t db_tok_number; 1464Srgrimeschar db_tok_string[TOK_STRING_SIZE]; 1474Srgrimes 14837504Sbdedb_expr_t db_radix = 16; 1494Srgrimes 1504Srgrimesvoid 151273265Spfgdb_flush_lex(void) 1524Srgrimes{ 1534Srgrimes db_flush_line(); 1544Srgrimes db_look_char = 0; 1554Srgrimes db_look_token = 0; 1564Srgrimes} 1574Srgrimes 1582112Swollmanstatic int 159273265Spfgdb_lex(void) 1604Srgrimes{ 1614Srgrimes int c; 1624Srgrimes 1634Srgrimes c = db_read_char(); 1644Srgrimes while (c <= ' ' || c > '~') { 1654Srgrimes if (c == '\n' || c == -1) 1664Srgrimes return (tEOL); 1674Srgrimes c = db_read_char(); 1684Srgrimes } 1694Srgrimes 1704Srgrimes if (c >= '0' && c <= '9') { 1714Srgrimes /* number */ 172798Swollman int r, digit = 0; 1734Srgrimes 1744Srgrimes if (c > '0') 1754Srgrimes r = db_radix; 1764Srgrimes else { 1774Srgrimes c = db_read_char(); 1784Srgrimes if (c == 'O' || c == 'o') 1794Srgrimes r = 8; 1804Srgrimes else if (c == 'T' || c == 't') 1814Srgrimes r = 10; 1824Srgrimes else if (c == 'X' || c == 'x') 1834Srgrimes r = 16; 1844Srgrimes else { 1854Srgrimes r = db_radix; 1864Srgrimes db_unread_char(c); 1874Srgrimes } 1884Srgrimes c = db_read_char(); 1894Srgrimes } 1904Srgrimes db_tok_number = 0; 1914Srgrimes for (;;) { 1924Srgrimes if (c >= '0' && c <= ((r == 8) ? '7' : '9')) 1934Srgrimes digit = c - '0'; 1944Srgrimes else if (r == 16 && ((c >= 'A' && c <= 'F') || 1954Srgrimes (c >= 'a' && c <= 'f'))) { 1964Srgrimes if (c >= 'a') 1974Srgrimes digit = c - 'a' + 10; 1984Srgrimes else if (c >= 'A') 1994Srgrimes digit = c - 'A' + 10; 2004Srgrimes } 2014Srgrimes else 2024Srgrimes break; 2034Srgrimes db_tok_number = db_tok_number * r + digit; 2044Srgrimes c = db_read_char(); 2054Srgrimes } 2064Srgrimes if ((c >= '0' && c <= '9') || 2074Srgrimes (c >= 'A' && c <= 'Z') || 2084Srgrimes (c >= 'a' && c <= 'z') || 2094Srgrimes (c == '_')) 2104Srgrimes { 2114Srgrimes db_error("Bad character in number\n"); 2124Srgrimes db_flush_lex(); 2134Srgrimes return (tEOF); 2144Srgrimes } 2154Srgrimes db_unread_char(c); 2164Srgrimes return (tNUMBER); 2174Srgrimes } 2184Srgrimes if ((c >= 'A' && c <= 'Z') || 2194Srgrimes (c >= 'a' && c <= 'z') || 2204Srgrimes c == '_' || c == '\\') 2214Srgrimes { 2224Srgrimes /* string */ 2234Srgrimes char *cp; 2244Srgrimes 2254Srgrimes cp = db_tok_string; 2264Srgrimes if (c == '\\') { 2274Srgrimes c = db_read_char(); 2284Srgrimes if (c == '\n' || c == -1) 2294Srgrimes db_error("Bad escape\n"); 2304Srgrimes } 2314Srgrimes *cp++ = c; 2324Srgrimes while (1) { 2334Srgrimes c = db_read_char(); 2344Srgrimes if ((c >= 'A' && c <= 'Z') || 2354Srgrimes (c >= 'a' && c <= 'z') || 2364Srgrimes (c >= '0' && c <= '9') || 23792011Sdfr c == '_' || c == '\\' || c == ':' || c == '.') 2384Srgrimes { 2394Srgrimes if (c == '\\') { 2404Srgrimes c = db_read_char(); 2414Srgrimes if (c == '\n' || c == -1) 2424Srgrimes db_error("Bad escape\n"); 2434Srgrimes } 2444Srgrimes *cp++ = c; 2454Srgrimes if (cp == db_tok_string+sizeof(db_tok_string)) { 2464Srgrimes db_error("String too long\n"); 2474Srgrimes db_flush_lex(); 2484Srgrimes return (tEOF); 2494Srgrimes } 2504Srgrimes continue; 2514Srgrimes } 2524Srgrimes else { 2534Srgrimes *cp = '\0'; 2544Srgrimes break; 2554Srgrimes } 2564Srgrimes } 2574Srgrimes db_unread_char(c); 2584Srgrimes return (tIDENT); 2594Srgrimes } 2604Srgrimes 2614Srgrimes switch (c) { 2624Srgrimes case '+': 2634Srgrimes return (tPLUS); 2644Srgrimes case '-': 2654Srgrimes return (tMINUS); 2664Srgrimes case '.': 2674Srgrimes c = db_read_char(); 2684Srgrimes if (c == '.') 2694Srgrimes return (tDOTDOT); 2704Srgrimes db_unread_char(c); 2714Srgrimes return (tDOT); 2724Srgrimes case '*': 2734Srgrimes return (tSTAR); 2744Srgrimes case '/': 2754Srgrimes return (tSLASH); 2764Srgrimes case '=': 2774Srgrimes return (tEQ); 2784Srgrimes case '%': 2794Srgrimes return (tPCT); 2804Srgrimes case '#': 2814Srgrimes return (tHASH); 2824Srgrimes case '(': 2834Srgrimes return (tLPAREN); 2844Srgrimes case ')': 2854Srgrimes return (tRPAREN); 2864Srgrimes case ',': 2874Srgrimes return (tCOMMA); 2884Srgrimes case '"': 2894Srgrimes return (tDITTO); 2904Srgrimes case '$': 2914Srgrimes return (tDOLLAR); 2924Srgrimes case '!': 2934Srgrimes return (tEXCL); 294174914Srwatson case ';': 295174914Srwatson return (tSEMI); 2964Srgrimes case '<': 2974Srgrimes c = db_read_char(); 2984Srgrimes if (c == '<') 2994Srgrimes return (tSHIFT_L); 3004Srgrimes db_unread_char(c); 3014Srgrimes break; 3024Srgrimes case '>': 3034Srgrimes c = db_read_char(); 3044Srgrimes if (c == '>') 3054Srgrimes return (tSHIFT_R); 3064Srgrimes db_unread_char(c); 3074Srgrimes break; 3084Srgrimes case -1: 3094Srgrimes return (tEOF); 3104Srgrimes } 3114Srgrimes db_printf("Bad character\n"); 3124Srgrimes db_flush_lex(); 3134Srgrimes return (tEOF); 3144Srgrimes} 315