Home | History | Annotate | Line # | Download | only in ddb
db_lex.c revision 1.7
      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 (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_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