Home | History | Annotate | Line # | Download | only in ddb
db_lex.c revision 1.4
      1 /*	$NetBSD: db_lex.c,v 1.4 1994/06/29 06:31:10 cgd 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 <ddb/db_lex.h>
     36 
     37 char	db_line[120];
     38 char *	db_lp, *db_endlp;
     39 
     40 int
     41 db_read_line()
     42 {
     43 	int	i;
     44 
     45 	i = db_readline(db_line, sizeof(db_line));
     46 	if (i == 0)
     47 	    return (0);	/* EOI */
     48 	db_lp = db_line;
     49 	db_endlp = db_lp + i;
     50 	return (i);
     51 }
     52 
     53 void
     54 db_flush_line()
     55 {
     56 	db_lp = db_line;
     57 	db_endlp = db_line;
     58 }
     59 
     60 int	db_look_char = 0;
     61 
     62 int
     63 db_read_char()
     64 {
     65 	int	c;
     66 
     67 	if (db_look_char != 0) {
     68 	    c = db_look_char;
     69 	    db_look_char = 0;
     70 	}
     71 	else if (db_lp >= db_endlp)
     72 	    c = -1;
     73 	else
     74 	    c = *db_lp++;
     75 	return (c);
     76 }
     77 
     78 void
     79 db_unread_char(c)
     80 {
     81 	db_look_char = c;
     82 }
     83 
     84 int	db_look_token = 0;
     85 
     86 void
     87 db_unread_token(t)
     88 	int	t;
     89 {
     90 	db_look_token = t;
     91 }
     92 
     93 int
     94 db_read_token()
     95 {
     96 	int	t;
     97 
     98 	if (db_look_token) {
     99 	    t = db_look_token;
    100 	    db_look_token = 0;
    101 	}
    102 	else
    103 	    t = db_lex();
    104 	return (t);
    105 }
    106 
    107 int	db_tok_number;
    108 char	db_tok_string[TOK_STRING_SIZE];
    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 		db_flush_lex();
    175 		return (tEOF);
    176 	    }
    177 	    db_unread_char(c);
    178 	    return (tNUMBER);
    179 	}
    180 	if ((c >= 'A' && c <= 'Z') ||
    181 	    (c >= 'a' && c <= 'z') ||
    182 	    c == '_' || c == '\\')
    183 	{
    184 	    /* string */
    185 	    char *cp;
    186 
    187 	    cp = db_tok_string;
    188 	    if (c == '\\') {
    189 		c = db_read_char();
    190 		if (c == '\n' || c == -1)
    191 		    db_error("Bad escape\n");
    192 	    }
    193 	    *cp++ = c;
    194 	    while (1) {
    195 		c = db_read_char();
    196 		if ((c >= 'A' && c <= 'Z') ||
    197 		    (c >= 'a' && c <= 'z') ||
    198 		    (c >= '0' && c <= '9') ||
    199 		    c == '_' || c == '\\' || c == ':')
    200 		{
    201 		    if (c == '\\') {
    202 			c = db_read_char();
    203 			if (c == '\n' || c == -1)
    204 			    db_error("Bad escape\n");
    205 		    }
    206 		    *cp++ = c;
    207 		    if (cp == db_tok_string+sizeof(db_tok_string)) {
    208 			db_error("String too long\n");
    209 			db_flush_lex();
    210 			return (tEOF);
    211 		    }
    212 		    continue;
    213 		}
    214 		else {
    215 		    *cp = '\0';
    216 		    break;
    217 		}
    218 	    }
    219 	    db_unread_char(c);
    220 	    return (tIDENT);
    221 	}
    222 
    223 	switch (c) {
    224 	    case '+':
    225 		return (tPLUS);
    226 	    case '-':
    227 		return (tMINUS);
    228 	    case '.':
    229 		c = db_read_char();
    230 		if (c == '.')
    231 		    return (tDOTDOT);
    232 		db_unread_char(c);
    233 		return (tDOT);
    234 	    case '*':
    235 		return (tSTAR);
    236 	    case '/':
    237 		return (tSLASH);
    238 	    case '=':
    239 		return (tEQ);
    240 	    case '%':
    241 		return (tPCT);
    242 	    case '#':
    243 		return (tHASH);
    244 	    case '(':
    245 		return (tLPAREN);
    246 	    case ')':
    247 		return (tRPAREN);
    248 	    case ',':
    249 		return (tCOMMA);
    250 	    case '"':
    251 		return (tDITTO);
    252 	    case '$':
    253 		return (tDOLLAR);
    254 	    case '!':
    255 		return (tEXCL);
    256 	    case '<':
    257 		c = db_read_char();
    258 		if (c == '<')
    259 		    return (tSHIFT_L);
    260 		db_unread_char(c);
    261 		break;
    262 	    case '>':
    263 		c = db_read_char();
    264 		if (c == '>')
    265 		    return (tSHIFT_R);
    266 		db_unread_char(c);
    267 		break;
    268 	    case -1:
    269 		return (tEOF);
    270 	}
    271 	db_printf("Bad character\n");
    272 	db_flush_lex();
    273 	return (tEOF);
    274 }
    275