Home | History | Annotate | Line # | Download | only in ddb
db_lex.c revision 1.5
      1 /*	$NetBSD: db_lex.c,v 1.5 1994/10/09 08:19:35 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 (at) 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_tok_number;
    111 char	db_tok_string[TOK_STRING_SIZE];
    112 
    113 int	db_radix = 16;
    114 
    115 void
    116 db_flush_lex()
    117 {
    118 	db_flush_line();
    119 	db_look_char = 0;
    120 	db_look_token = 0;
    121 }
    122 
    123 int
    124 db_lex()
    125 {
    126 	int	c;
    127 
    128 	c = db_read_char();
    129 	while (c <= ' ' || c > '~') {
    130 	    if (c == '\n' || c == -1)
    131 		return (tEOL);
    132 	    c = db_read_char();
    133 	}
    134 
    135 	if (c >= '0' && c <= '9') {
    136 	    /* number */
    137 	    int	r, digit;
    138 
    139 	    if (c > '0')
    140 		r = db_radix;
    141 	    else {
    142 		c = db_read_char();
    143 		if (c == 'O' || c == 'o')
    144 		    r = 8;
    145 		else if (c == 'T' || c == 't')
    146 		    r = 10;
    147 		else if (c == 'X' || c == 'x')
    148 		    r = 16;
    149 		else {
    150 		    r = db_radix;
    151 		    db_unread_char(c);
    152 		}
    153 		c = db_read_char();
    154 	    }
    155 	    db_tok_number = 0;
    156 	    for (;;) {
    157 		if (c >= '0' && c <= ((r == 8) ? '7' : '9'))
    158 		    digit = c - '0';
    159 		else if (r == 16 && ((c >= 'A' && c <= 'F') ||
    160 				     (c >= 'a' && c <= 'f'))) {
    161 		    if (c >= 'a')
    162 			digit = c - 'a' + 10;
    163 		    else if (c >= 'A')
    164 			digit = c - 'A' + 10;
    165 		}
    166 		else
    167 		    break;
    168 		db_tok_number = db_tok_number * r + digit;
    169 		c = db_read_char();
    170 	    }
    171 	    if ((c >= '0' && c <= '9') ||
    172 		(c >= 'A' && c <= 'Z') ||
    173 		(c >= 'a' && c <= 'z') ||
    174 		(c == '_'))
    175 	    {
    176 		db_error("Bad character in number\n");
    177 		db_flush_lex();
    178 		return (tEOF);
    179 	    }
    180 	    db_unread_char(c);
    181 	    return (tNUMBER);
    182 	}
    183 	if ((c >= 'A' && c <= 'Z') ||
    184 	    (c >= 'a' && c <= 'z') ||
    185 	    c == '_' || c == '\\')
    186 	{
    187 	    /* string */
    188 	    char *cp;
    189 
    190 	    cp = db_tok_string;
    191 	    if (c == '\\') {
    192 		c = db_read_char();
    193 		if (c == '\n' || c == -1)
    194 		    db_error("Bad escape\n");
    195 	    }
    196 	    *cp++ = c;
    197 	    while (1) {
    198 		c = db_read_char();
    199 		if ((c >= 'A' && c <= 'Z') ||
    200 		    (c >= 'a' && c <= 'z') ||
    201 		    (c >= '0' && c <= '9') ||
    202 		    c == '_' || c == '\\' || c == ':')
    203 		{
    204 		    if (c == '\\') {
    205 			c = db_read_char();
    206 			if (c == '\n' || c == -1)
    207 			    db_error("Bad escape\n");
    208 		    }
    209 		    *cp++ = c;
    210 		    if (cp == db_tok_string+sizeof(db_tok_string)) {
    211 			db_error("String too long\n");
    212 			db_flush_lex();
    213 			return (tEOF);
    214 		    }
    215 		    continue;
    216 		}
    217 		else {
    218 		    *cp = '\0';
    219 		    break;
    220 		}
    221 	    }
    222 	    db_unread_char(c);
    223 	    return (tIDENT);
    224 	}
    225 
    226 	switch (c) {
    227 	    case '+':
    228 		return (tPLUS);
    229 	    case '-':
    230 		return (tMINUS);
    231 	    case '.':
    232 		c = db_read_char();
    233 		if (c == '.')
    234 		    return (tDOTDOT);
    235 		db_unread_char(c);
    236 		return (tDOT);
    237 	    case '*':
    238 		return (tSTAR);
    239 	    case '/':
    240 		return (tSLASH);
    241 	    case '=':
    242 		return (tEQ);
    243 	    case '%':
    244 		return (tPCT);
    245 	    case '#':
    246 		return (tHASH);
    247 	    case '(':
    248 		return (tLPAREN);
    249 	    case ')':
    250 		return (tRPAREN);
    251 	    case ',':
    252 		return (tCOMMA);
    253 	    case '"':
    254 		return (tDITTO);
    255 	    case '$':
    256 		return (tDOLLAR);
    257 	    case '!':
    258 		return (tEXCL);
    259 	    case '<':
    260 		c = db_read_char();
    261 		if (c == '<')
    262 		    return (tSHIFT_L);
    263 		db_unread_char(c);
    264 		break;
    265 	    case '>':
    266 		c = db_read_char();
    267 		if (c == '>')
    268 		    return (tSHIFT_R);
    269 		db_unread_char(c);
    270 		break;
    271 	    case -1:
    272 		return (tEOF);
    273 	}
    274 	db_printf("Bad character\n");
    275 	db_flush_lex();
    276 	return (tEOF);
    277 }
    278