scanner.c

来自「早期freebsd实现」· C语言 代码 · 共 864 行 · 第 1/2 页

C
864
字号
/* * Copyright (c) 1983 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)scanner.c	5.3 (Berkeley) 6/1/90";#endif /* not lint *//* * Debugger scanner. */#include "defs.h"#include "scanner.h"#include "main.h"#include "keywords.h"#include "tree.h"#include "symbols.h"#include "names.h"#include "y.tab.h"#ifndef publictypedef int Token;#define MAXLINESIZE 10240#endifpublic String initfile = ".dbxinit";typedef enum { WHITE, ALPHA, NUM, OTHER } Charclass;private Charclass class[256 + 1];private Charclass *lexclass = class + 1;#define isdigit(c) (lexclass[c] == NUM)#define isalnum(c) (lexclass[c] == ALPHA or lexclass[c] == NUM)#define ishexdigit(c) ( \    isdigit(c) or (c >= 'a' and c <= 'f') or (c >= 'A' and c <= 'F') \)public boolean chkalias;public char scanner_linebuf[MAXLINESIZE];private File in;private char *curchar, *prevchar;#define MAXINCLDEPTH 10private struct {    File savefile;    Filename savefn;    int savelineno;} inclinfo[MAXINCLDEPTH];private unsigned int curinclindex;private Token getident();private Token getnum();private Token getstring();private Boolean eofinput();private char charcon();private enterlexclass(class, s)Charclass class;String s;{    register char *p;    for (p = s; *p != '\0'; p++) {	lexclass[*p] = class;    }}public scanner_init(){    register Integer i;    for (i = 0; i < 257; i++) {	class[i] = OTHER;    }    enterlexclass(WHITE, " \t");    enterlexclass(ALPHA, "abcdefghijklmnopqrstuvwxyz");    enterlexclass(ALPHA, "ABCDEFGHIJKLMNOPQRSTUVWXYZ_$");    enterlexclass(NUM, "0123456789");    in = stdin;    errfilename = nil;    errlineno = 0;    curchar = scanner_linebuf;    scanner_linebuf[0] = '\0';    chkalias = true;}/* * Read a single token. * * The input is line buffered.  Tokens cannot cross line boundaries. * * There are two "modes" of operation:  one as in a compiler, * and one for reading shell-like syntax.  In the first mode * there is the additional choice of doing alias processing. */private Boolean shellmode;public Token yylex(){    register int c;    register char *p;    register Token t;    String line;    integer n;    p = curchar;    if (*p == '\0') {	do {	    if (isterm(in)) {		printf("(%s) ", cmdname);	    }	    fflush(stdout);	    line = fgets(scanner_linebuf, MAXLINESIZE, in);	} while (line == nil and not eofinput());	if (line == nil) {	    c = EOF;	} else {	    p = scanner_linebuf;	    while (lexclass[*p] == WHITE) {		p++;	    }	    shellmode = false;	}	chkalias = true;    } else {	while (lexclass[*p] == WHITE) {	    p++;	}    }    curchar = p;    prevchar = curchar;    c = *p;    if (lexclass[c] == ALPHA) {	t = getident(chkalias);    } else if (lexclass[c] == NUM) {	if (shellmode) {	    t = getident(chkalias);	} else {	    t = getnum();	}    } else {	++curchar;	switch (c) {	    case '\n':		t = '\n';		if (errlineno != 0) {		    errlineno++;		}		break;	    case '"':	    case '\'':		t = getstring(c);		break;	    case '.':		if (shellmode) {		    --curchar;		    t = getident(chkalias);		} else if (isdigit(*curchar)) {		    --curchar;		    t = getnum();		} else {		    t = '.';		}		break;	    case '-':		if (shellmode) {		    --curchar;		    t = getident(chkalias);		} else if (*curchar == '>') {		    ++curchar;		    t = ARROW;		} else {		    t = '-';		}		break;	    case '#':		if (not isterm(in)) {		    *p = '\0';		    curchar = p;		    t = '\n';		    ++errlineno;		} else {		    t = '#';		}		break;	    case '\\':		if (*(p+1) == '\n') {		    n = MAXLINESIZE - (p - &scanner_linebuf[0]);		    if (n > 1) {			if (fgets(p, n, in) == nil) {			    t = 0;			} else {			    curchar = p;			    t = yylex();			}		    } else {			t = '\\';		    }		} else {		    t = '\\';		}		break;	    case EOF:		t = 0;		break;	    default:		if (shellmode and index("!&*<>()[]", c) == nil) {		    --curchar;		    t = getident(chkalias);		} else {		    t = c;		}		break;	}    }    chkalias = false;#   ifdef LEXDEBUG	if (lexdebug) {	    fprintf(stderr, "yylex returns ");	    print_token(stderr, t);	    fprintf(stderr, "\n");	}#   endif    return t;}/* * Put the given string before the current character * in the current line, thus inserting it into the input stream. */public insertinput (s)String s;{    register char *p, *q;    int need, avail, shift;    q = s;    need = strlen(q);    avail = curchar - &scanner_linebuf[0];    if (need <= avail) {	curchar = &scanner_linebuf[avail - need];	p = curchar;	while (*q != '\0') {	    *p++ = *q++;	}    } else {	p = curchar;	while (*p != '\0') {	    ++p;	}	shift = need - avail;	if (p + shift >= &scanner_linebuf[MAXLINESIZE]) {	    error("alias expansion too large");	}	for (;;) {	    *(p + shift) = *p;	    if (p == curchar) {		break;	    }	    --p;	}	p = &scanner_linebuf[0];	while (*q != '\0') {	    *p++ = *q++;	}	curchar = &scanner_linebuf[0];    }}/* * Get the actuals for a macro call. */private String movetochar (str, c)String str;char c;{    register char *p;    while (*p != c) {	if (*p == '\0') {	    error("missing ')' in macro call");	} else if (*p == ')') {	    error("not enough parameters in macro call");	} else if (*p == ',') {	    error("too many parameters in macro call");	}	++p;    }    return p;}private String *getactuals (n)integer n;{    String *a;    register char *p;    int i;    a = newarr(String, n);    p = curchar;    while (*p != '(') {	if (lexclass[*p] != WHITE) {	    error("missing actuals for macro");	}	++p;    }    ++p;    for (i = 0; i < n - 1; i++) {	a[i] = p;	p = movetochar(p, ',');	*p = '\0';	++p;    }    a[n-1] = p;    p = movetochar(p, ')');    *p = '\0';    curchar = p + 1;    return a;}/* * Do command macro expansion, assuming curchar points to the beginning * of the actuals, and we are not in shell mode. */private expand (pl, str)List pl;String str;{    char buf[4096], namebuf[100];    register char *p, *q, *r;    String *actual;    Name n;    integer i;    boolean match;    if (pl == nil) {	insertinput(str);    } else {	actual = getactuals(list_size(pl));	p = buf;	q = str;	while (*q != '\0') {	    if (p >= &buf[4096]) {		error("alias expansion too large");	    }	    if (lexclass[*q] == ALPHA) {		r = namebuf;		do {		    *r++ = *q++;		} while (isalnum(*q));		*r = '\0';		i = 0;		match = false;		foreach(Name, n, pl)		    if (streq(ident(n), namebuf)) {			match = true;			break;		    }		    ++i;		endfor		if (match) {		    r = actual[i];		} else {		    r = namebuf;		}		while (*r != '\0') {		    *p++ = *r++;		}	    } else {		*p++ = *q++;	    }	}	*p = '\0';	insertinput(buf);    }}/* * Parser error handling. */public yyerror(s)String s;{    register char *p;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?