📄 scanner.c
字号:
/************************************************************************ * * * Copyright (c) 1986, 1989 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * * * Modification History * * * * 005 - Made # and \ work as expected in shellmode. * * (Jon Reeves, January 21, 1989) * * * * 004 - Added a <cr> for the -x option for use with xdb * * (David Metsky, March 8, 1988) * * * * 003 - Merged in 4.3 changes. * * (vjh, April 29, 1986) * * * * 002 - Update copyright. * * (vjh, August 23, 1985) * * * * 001 - Added saved-command feature: <cr> alone on a command * * line reexecutes previously entered command. * * (Victoria Holt, April 9, 1985) * * * ************************************************************************//* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. *//* derived from: "@(#)scanner.c 5.1 (Berkeley) 5/31/85" */#ifndef lintstatic char sccsid[] = "@(#)scanner.c 4.2 ULTRIX 11/9/90";#endif not lintstatic char rcsid[] = "$Header: scanner.c,v 1.5 84/12/26 10:42:05 linton Exp $";/* * 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;public boolean xdb; /* xdb specific features */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 File recorded_input;private char *record_name = nil;private char *curchar, *prevchar;private char prevbuf[MAXLINESIZE];#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 set_record(string)char *string;{ if(record_name != nil) { fclose(recorded_input); record_name = nil; } if(strlen(string)) { if((recorded_input = fopen(string, "w")) != nil) { record_name = strdup(string); } else { error("unable to open %s for recording", string); } }}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'; prevbuf[0] = '\n'; 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); if (xdb) { /* 004 - DNM */ printf("\n"); } } 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++; } if (*p == '\n') { strcpy(scanner_linebuf, prevbuf); p = scanner_linebuf; } else { strcpy(prevbuf, p); } shellmode = false; } Iline_alloc(p); if(record_name != nil) { fputs(p, recorded_input); } 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 (shellmode) { --curchar; t = getident(chkalias); } else 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 { if (shellmode) { --curchar; t = getident(chkalias); } else { t = '\\'; } } } else { if (shellmode) { --curchar; t = getident(chkalias); } 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 if(t == DELETE) { char *tmp; if(strncmp((tmp = (char *)strpbrk(line, "a")), "all", 3) == 0) { tmp[0] = '*'; tmp[1] = ' '; tmp[2] = ' '; } } 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -