⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 toke.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $RCSfile: toke.c,v $$Revision: 4.0.1.9 $$Date: 1993/02/05 19:48:43 $ * *    Copyright (c) 1991, Larry Wall * *    You may distribute under the terms of either the GNU General Public *    License or the Artistic License, as specified in the README file. * * $Log: toke.c,v $ * Revision 4.0.1.9  1993/02/05  19:48:43  lwall * patch36: now detects ambiguous use of filetest operators as well as unary * patch36: fixed ambiguity on - within tr/// * * Revision 4.0.1.8  92/06/23  12:33:45  lwall * patch35: bad interaction between backslash and hyphen in tr/// *  * Revision 4.0.1.7  92/06/11  21:16:30  lwall * patch34: expectterm incorrectly set to indicate start of program or block *  * Revision 4.0.1.6  92/06/08  16:03:49  lwall * patch20: an EXPR may now start with a bareword * patch20: print $fh EXPR can now expect term rather than operator in EXPR * patch20: added ... as variant on .. * patch20: new warning on spurious backslash * patch20: new warning on missing $ for foreach variable * patch20: "foo"x1024 now legal without space after x * patch20: new warning on print accidentally used as function * patch20: tr/stuff// wasn't working right * patch20: 2. now eats the dot * patch20: <@ARGV> now notices @ARGV * patch20: tr/// now lets you say \- *  * Revision 4.0.1.5  91/11/11  16:45:51  lwall * patch19: default arg for shift was wrong after first subroutine definition *  * Revision 4.0.1.4  91/11/05  19:02:48  lwall * patch11: \x and \c were subject to double interpretation in regexps * patch11: prepared for ctype implementations that don't define isascii() * patch11: nested list operators could miscount parens * patch11: once-thru blocks didn't display right in the debugger * patch11: sort eval "whatever" didn't work * patch11: underscore is now allowed within literal octal and hex numbers *  * Revision 4.0.1.3  91/06/10  01:32:26  lwall * patch10: m'$foo' now treats string as single quoted * patch10: certain pattern optimizations were botched *  * Revision 4.0.1.2  91/06/07  12:05:56  lwall * patch4: new copyright notice * patch4: debugger lost track of lines in eval * patch4: //o and s///o now optimize themselves fully at runtime * patch4: added global modifier for pattern matches *  * Revision 4.0.1.1  91/04/12  09:18:18  lwall * patch1: perl -de "print" wouldn't stop at the first statement *  * Revision 4.0  91/03/20  01:42:14  lwall * 4.0 baseline. *  */#include "EXTERN.h"#include "perl.h"#include "perly.h"static void set_csh();#ifdef I_FCNTL#include <fcntl.h>#endif#ifdef I_SYS_FILE#include <sys/file.h>#endif#ifdef f_next#undef f_next#endif/* which backslash sequences to keep in m// or s// */static char *patleave = "\\.^$@dDwWsSbB+*?|()-nrtfeaxc0123456789[{]}";char *reparse;		/* if non-null, scanident found ${foo[$bar]} */void checkcomma();#ifdef CLINE#undef CLINE#endif#define CLINE (cmdline = (curcmd->c_line < cmdline ? curcmd->c_line : cmdline))#ifdef atarist#define PERL_META(c) ((c) | 128)#else#define META(c) ((c) | 128)#endif#define RETURN(retval) return (bufptr = s,(int)retval)#define OPERATOR(retval) return (expectterm = TRUE,bufptr = s,(int)retval)#define TERM(retval) return (CLINE, expectterm = FALSE,bufptr = s,(int)retval)#define LOOPX(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)LOOPEX)#define FTST(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)FILETEST)#define FUN0(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC0)#define FUN1(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC1)#define FUN2(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC2)#define FUN2x(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC2x)#define FUN3(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC3)#define FUN4(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC4)#define FUN5(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC5)#define FL(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FLIST)#define FL2(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FLIST2)#define HFUN(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)HSHFUN)#define HFUN3(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)HSHFUN3)#define LFUN(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LVALFUN)#define AOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)ADDOP)#define MOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)MULOP)#define EOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)EQOP)#define ROP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)RELOP)#define FOP(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP)#define FOP2(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP2)#define FOP3(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP3)#define FOP4(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP4)#define FOP22(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP22)#define FOP25(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP25)static char *last_uni;/* This bit of chicanery makes a unary function followed by * a parenthesis into a function with one argument, highest precedence. */#define UNI(f) return(yylval.ival = f, \	expectterm = TRUE, \	bufptr = s, \	last_uni = oldbufptr, \	(*s == '(' || (s = skipspace(s), *s == '(') ? (int)FUNC1 : (int)UNIOP) )/* This does similarly for list operators, merely by pretending that the * paren came before the listop rather than after. */#ifdef atarist#define LOP(f) return(CLINE, *s == '(' || (s = skipspace(s), *s == '(') ? \	(*s = (char) PERL_META('('), bufptr = oldbufptr, '(') : \	(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LISTOP))#else#define LOP(f) return(CLINE, *s == '(' || (s = skipspace(s), *s == '(') ? \	(*s = (char) META('('), bufptr = oldbufptr, '(') : \	(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LISTOP))#endif/* grandfather return to old style */#define OLDLOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LISTOP)char *skipspace(s)register char *s;{    while (s < bufend && isSPACE(*s))	s++;    return s;}voidcheck_uni() {    char *s;    char ch;    if (oldoldbufptr != last_uni)	return;    while (isSPACE(*last_uni))	last_uni++;    for (s = last_uni; isALNUM(*s) || *s == '-'; s++) ;    ch = *s;    *s = '\0';    warn("Warning: Use of \"%s\" without parens is ambiguous", last_uni);    *s = ch;}#ifdef CRIPPLED_CC#undef UNI#undef LOP#define UNI(f) return uni(f,s)#define LOP(f) return lop(f,s)intuni(f,s)int f;char *s;{    yylval.ival = f;    expectterm = TRUE;    bufptr = s;    last_uni = oldbufptr;    if (*s == '(')	return FUNC1;    s = skipspace(s);    if (*s == '(')	return FUNC1;    else	return UNIOP;}intlop(f,s)int f;char *s;{    CLINE;    if (*s != '(')	s = skipspace(s);    if (*s == '(') {#ifdef atarist	*s = PERL_META('(');#else	*s = META('(');#endif	bufptr = oldbufptr;	return '(';    }    else {	yylval.ival=f;	expectterm = TRUE;	bufptr = s;	return LISTOP;    }}#endif /* CRIPPLED_CC */intyylex(){    register char *s = bufptr;    register char *d;    register int tmp;    static bool in_format = FALSE;    static bool firstline = TRUE;    extern int yychar;		/* last token */    oldoldbufptr = oldbufptr;    oldbufptr = s;  retry:#ifdef YYDEBUG    if (debug & 1)	if (index(s,'\n'))	    fprintf(stderr,"Tokener at %s",s);	else	    fprintf(stderr,"Tokener at %s\n",s);#endif#ifdef BADSWITCH    if (*s & 128) {	if ((*s & 127) == '(') {	    *s++ = '(';	    oldbufptr = s;	}	else if ((*s & 127) == '}') {	    *s++ = '}';	    RETURN('}');	}	else	    warn("Unrecognized character \\%03o ignored", *s++ & 255);	goto retry;    }#endif    switch (*s) {    default:	if ((*s & 127) == '(') {	    *s++ = '(';	    oldbufptr = s;	}	else if ((*s & 127) == '}') {	    *s++ = '}';	    RETURN('}');	}	else	    warn("Unrecognized character \\%03o ignored", *s++ & 255);	goto retry;    case 4:    case 26:	goto fake_eof;			/* emulate EOF on ^D or ^Z */    case 0:	if (!rsfp)	    RETURN(0);	if (s++ < bufend)	    goto retry;			/* ignore stray nulls */	last_uni = 0;	if (firstline) {	    firstline = FALSE;	    if (minus_n || minus_p || perldb) {		str_set(linestr,"");		if (perldb) {		    char *getenv();		    char *pdb = getenv("PERLDB");		    str_cat(linestr, pdb ? pdb : "require 'perldb.pl'");		    str_cat(linestr, ";");		}		if (minus_n || minus_p) {		    str_cat(linestr,"line: while (<>) {");		    if (minus_l)			str_cat(linestr,"chop;");		    if (minus_a)			str_cat(linestr,"@F=split(' ');");		}		oldoldbufptr = oldbufptr = s = str_get(linestr);		bufend = linestr->str_ptr + linestr->str_cur;		goto retry;	    }	}	if (in_format) {	    bufptr = bufend;	    yylval.formval = load_format();	    in_format = FALSE;	    oldoldbufptr = oldbufptr = s = str_get(linestr) + 1;	    bufend = linestr->str_ptr + linestr->str_cur;	    OPERATOR(FORMLIST);	}	curcmd->c_line++;#ifdef CRYPTSCRIPT	cryptswitch();#endif /* CRYPTSCRIPT */	do {	    if ((s = str_gets(linestr, rsfp, 0)) == Nullch) {	      fake_eof:		if (rsfp) {		    if (preprocess)			(void)mypclose(rsfp);		    else if ((FILE*)rsfp == stdin)			clearerr(stdin);		    else			(void)fclose(rsfp);		    rsfp = Nullfp;		}		if (minus_n || minus_p) {		    str_set(linestr,minus_p ? ";}continue{print" : "");		    str_cat(linestr,";}");		    oldoldbufptr = oldbufptr = s = str_get(linestr);		    bufend = linestr->str_ptr + linestr->str_cur;		    minus_n = minus_p = 0;		    goto retry;		}		oldoldbufptr = oldbufptr = s = str_get(linestr);		str_set(linestr,"");		RETURN(';');	/* not infinite loop because rsfp is NULL now */	    }	    if (doextract && *linestr->str_ptr == '#')		doextract = FALSE;	} while (doextract);	oldoldbufptr = oldbufptr = bufptr = s;	if (perldb) {	    STR *str = Str_new(85,0);	    str_sset(str,linestr);	    astore(stab_xarray(curcmd->c_filestab),(int)curcmd->c_line,str);	}#ifdef DEBUG	if (firstline) {	    char *showinput();	    s = showinput();	}#endif	bufend = linestr->str_ptr + linestr->str_cur;	if (curcmd->c_line == 1) {	    if (*s == '#' && s[1] == '!') {		if (!in_eval && !instr(s,"perl") && instr(origargv[0],"perl")) {		    char **newargv;		    char *cmd;		    s += 2;		    if (*s == ' ')			s++;		    cmd = s;		    while (s < bufend && !isSPACE(*s))			s++;		    *s++ = '\0';		    while (s < bufend && isSPACE(*s))			s++;		    if (s < bufend) {			Newz(899,newargv,origargc+3,char*);			newargv[1] = s;			while (s < bufend && !isSPACE(*s))			    s++;			*s = '\0';			Copy(origargv+1, newargv+2, origargc+1, char*);		    }		    else			newargv = origargv;		    newargv[0] = cmd;		    execv(cmd,newargv);		    fatal("Can't exec %s", cmd);		}	    }	    else {		while (s < bufend && isSPACE(*s))		    s++;		if (*s == ':')	/* for csh's that have to exec sh scripts */		    s++;	    }	}	goto retry;    case ' ': case '\t': case '\f': case '\r': case 013:	s++;	goto retry;    case '#':	if (preprocess && s == str_get(linestr) &&	       s[1] == ' ' && (isDIGIT(s[2]) || strnEQ(s+2,"line ",5)) ) {	    while (*s && !isDIGIT(*s))		s++;	    curcmd->c_line = atoi(s)-1;	    while (isDIGIT(*s))		s++;	    d = bufend;	    while (s < d && isSPACE(*s)) s++;	    s[strlen(s)-1] = '\0';	/* wipe out newline */	    if (*s == '"') {		s++;		s[strlen(s)-1] = '\0';	/* wipe out trailing quote */	    }	    if (*s)		curcmd->c_filestab = fstab(s);	    else		curcmd->c_filestab = fstab(origfilename);	    oldoldbufptr = oldbufptr = s = str_get(linestr);	}	/* FALL THROUGH */    case '\n':	if (in_eval && !rsfp) {	    d = bufend;	    while (s < d && *s != '\n')		s++;	    if (s < d)		s++;	    if (in_format) {		bufptr = s;		yylval.formval = load_format();		in_format = FALSE;		oldoldbufptr = oldbufptr = s = bufptr + 1;		TERM(FORMLIST);	    }	    curcmd->c_line++;	}	else {	    *s = '\0';	    bufend = s;	}	goto retry;    case '-':	if (s[1] && isALPHA(s[1]) && !isALPHA(s[2])) {	    s++;	    last_uni = oldbufptr;	    switch (*s++) {	    case 'r': FTST(O_FTEREAD);	    case 'w': FTST(O_FTEWRITE);	    case 'x': FTST(O_FTEEXEC);	    case 'o': FTST(O_FTEOWNED);	    case 'R': FTST(O_FTRREAD);	    case 'W': FTST(O_FTRWRITE);	    case 'X': FTST(O_FTREXEC);	    case 'O': FTST(O_FTROWNED);	    case 'e': FTST(O_FTIS);	    case 'z': FTST(O_FTZERO);	    case 's': FTST(O_FTSIZE);	    case 'f': FTST(O_FTFILE);	    case 'd': FTST(O_FTDIR);	    case 'l': FTST(O_FTLINK);	    case 'p': FTST(O_FTPIPE);	    case 'S': FTST(O_FTSOCK);	    case 'u': FTST(O_FTSUID);	    case 'g': FTST(O_FTSGID);	    case 'k': FTST(O_FTSVTX);	    case 'b': FTST(O_FTBLK);	    case 'c': FTST(O_FTCHR);	    case 't': FTST(O_FTTTY);	    case 'T': FTST(O_FTTEXT);	    case 'B': FTST(O_FTBINARY);	    case 'M': stabent("\024",TRUE); FTST(O_FTMTIME);	    case 'A': stabent("\024",TRUE); FTST(O_FTATIME);	    case 'C': stabent("\024",TRUE); FTST(O_FTCTIME);	    default:		s -= 2;		break;	    }	}	tmp = *s++;	if (*s == tmp) {	    s++;	    RETURN(DEC);	}	if (expectterm) {	    if (isSPACE(*s) || !isSPACE(*bufptr))		check_uni();	    OPERATOR('-');	}	else	    AOP(O_SUBTRACT);    case '+':	tmp = *s++;	if (*s == tmp) {	    s++;	    RETURN(INC);	}	if (expectterm) {	    if (isSPACE(*s) || !isSPACE(*bufptr))		check_uni();	    OPERATOR('+');	}	else	    AOP(O_ADD);    case '*':	if (expectterm) {	    check_uni();	    s = scanident(s,bufend,tokenbuf);	    yylval.stabval = stabent(tokenbuf,TRUE);	    TERM(STAR);	}	tmp = *s++;	if (*s == tmp) {	    s++;	    OPERATOR(POW);	}	MOP(O_MULTIPLY);    case '%':	if (expectterm) {	    if (!isALPHA(s[1]))		check_uni();	    s = scanident(s,bufend,tokenbuf);	    yylval.stabval = hadd(stabent(tokenbuf,TRUE));	    TERM(HSH);	}	s++;	MOP(O_MODULO);    case '^':    case '~':    case '(':    case ',':    case ':':    case '[':	tmp = *s++;	OPERATOR(tmp);    case '{':	tmp = *s++;	yylval.ival = curcmd->c_line;	if (isSPACE(*s) || *s == '#')	    cmdline = NOLINE;   /* invalidate current command line number */	expectterm = 2;	RETURN(tmp);    case ';':	if (curcmd->c_line < cmdline)	    cmdline = curcmd->c_line;	tmp = *s++;	OPERATOR(tmp);    case ')':

⌨️ 快捷键说明

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