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