lwall@netlabs.com (Larry Wall) (04/15/91)
Submitted-by: Larry Wall <lwall@netlabs.com> Posting-number: Volume 18, Issue 22 Archive-name: perl/part04 [There are 36 kits for perl version 4.0.] #! /bin/sh # Make a new directory for the perl sources, cd to it, and run kits 1 # thru 36 through sh. When all 36 kits have been run, read README. echo "This is perl 4.0 kit 4 (of 36). If kit 4 is complete, the line" echo '"'"End of kit 4 (of 36)"'" will echo at the end.' echo "" export PATH || (echo "You didn't use sh, you clunch." ; kill $$) mkdir 2>/dev/null echo Extracting toke.c:AA sed >toke.c:AA <<'!STUFFY!FUNK!' -e 's/X//' X/* $RCSfile: toke.c,v $$Revision: 4.0.1.1 $$Date: 91/04/12 09:18:18 $ X * X * Copyright (c) 1989, Larry Wall X * X * You may distribute under the terms of the GNU General Public License X * as specified in the README file that comes with the perl 3.0 kit. X * X * $Log: toke.c,v $ X * Revision 4.0.1.1 91/04/12 09:18:18 lwall X * patch1: perl -de "print" wouldn't stop at the first statement X * X * Revision 4.0 91/03/20 01:42:14 lwall X * 4.0 baseline. X * X */ X X#include "EXTERN.h" X#include "perl.h" X#include "perly.h" X X#ifdef I_FCNTL X#include <fcntl.h> X#endif X#ifdef I_SYS_FILE X#include <sys/file.h> X#endif X X/* which backslash sequences to keep in m// or s// */ X Xstatic char *patleave = "\\.^$@dDwWsSbB+*?|()-nrtf0123456789[{]}"; X Xchar *reparse; /* if non-null, scanident found ${foo[$bar]} */ X Xvoid checkcomma(); X X#ifdef CLINE X#undef CLINE X#endif X#define CLINE (cmdline = (curcmd->c_line < cmdline ? curcmd->c_line : cmdline)) X X#define META(c) ((c) | 128) X X#define RETURN(retval) return (bufptr = s,(int)retval) X#define OPERATOR(retval) return (expectterm = TRUE,bufptr = s,(int)retval) X#define TERM(retval) return (CLINE, expectterm = FALSE,bufptr = s,(int)retval) X#define LOOPX(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)LOOPEX) X#define FTST(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)FILETEST) X#define FUN0(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC0) X#define FUN1(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC1) X#define FUN2(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC2) X#define FUN2x(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC2x) X#define FUN3(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC3) X#define FUN4(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC4) X#define FUN5(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC5) X#define FL(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FLIST) X#define FL2(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FLIST2) X#define HFUN(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)HSHFUN) X#define HFUN3(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)HSHFUN3) X#define LFUN(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LVALFUN) X#define AOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)ADDOP) X#define MOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)MULOP) X#define EOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)EQOP) X#define ROP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)RELOP) X#define FOP(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP) X#define FOP2(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP2) X#define FOP3(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP3) X#define FOP4(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP4) X#define FOP22(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP22) X#define FOP25(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP25) X X/* This bit of chicanery makes a unary function followed by X * a parenthesis into a function with one argument, highest precedence. X */ X#define UNI(f) return(yylval.ival = f,expectterm = TRUE,bufptr = s, \ X (*s == '(' || (s = skipspace(s), *s == '(') ? (int)FUNC1 : (int)UNIOP) ) X X/* This does similarly for list operators, merely by pretending that the X * paren came before the listop rather than after. X */ X#define LOP(f) return(CLINE, *s == '(' || (s = skipspace(s), *s == '(') ? \ X (*s = META('('), bufptr = oldbufptr, '(') : \ X (yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LISTOP)) X/* grandfather return to old style */ X#define OLDLOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LISTOP) X Xchar * Xskipspace(s) Xregister char *s; X{ X while (s < bufend && isascii(*s) && isspace(*s)) X s++; X return s; X} X X#ifdef CRIPPLED_CC X X#undef UNI X#undef LOP X#define UNI(f) return uni(f,s) X#define LOP(f) return lop(f,s) X Xint Xuni(f,s) Xint f; Xchar *s; X{ X yylval.ival = f; X expectterm = TRUE; X bufptr = s; X if (*s == '(') X return FUNC1; X s = skipspace(s); X if (*s == '(') X return FUNC1; X else X return UNIOP; X} X Xint Xlop(f,s) Xint f; Xchar *s; X{ X CLINE; X if (*s != '(') X s = skipspace(s); X if (*s == '(') { X *s = META('('); X bufptr = oldbufptr; X return '('; X } X else { X yylval.ival=f; X expectterm = TRUE; X bufptr = s; X return LISTOP; X } X} X X#endif /* CRIPPLED_CC */ X Xyylex() X{ X register char *s = bufptr; X register char *d; X register int tmp; X static bool in_format = FALSE; X static bool firstline = TRUE; X extern int yychar; /* last token */ X X oldoldbufptr = oldbufptr; X oldbufptr = s; X X retry: X#ifdef YYDEBUG X if (debug & 1) X if (index(s,'\n')) X fprintf(stderr,"Tokener at %s",s); X else X fprintf(stderr,"Tokener at %s\n",s); X#endif X#ifdef BADSWITCH X if (*s & 128) { X if ((*s & 127) == '(') X *s++ = '('; X else X warn("Unrecognized character \\%03o ignored", *s++ & 255); X goto retry; X } X#endif X switch (*s) { X default: X if ((*s & 127) == '(') X *s++ = '('; X else X warn("Unrecognized character \\%03o ignored", *s++ & 255); X goto retry; X case 4: X case 26: X goto fake_eof; /* emulate EOF on ^D or ^Z */ X case 0: X if (!rsfp) X RETURN(0); X if (s++ < bufend) X goto retry; /* ignore stray nulls */ X if (firstline) { X firstline = FALSE; X if (minus_n || minus_p || perldb) { X str_set(linestr,""); X if (perldb) { X char *getenv(); X char *pdb = getenv("PERLDB"); X X str_cat(linestr, pdb ? pdb : "require 'perldb.pl'"); X str_cat(linestr, ";"); X } X if (minus_n || minus_p) { X str_cat(linestr,"line: while (<>) {"); X if (minus_l) X str_cat(linestr,"chop;"); X if (minus_a) X str_cat(linestr,"@F=split(' ');"); X } X oldoldbufptr = oldbufptr = s = str_get(linestr); X bufend = linestr->str_ptr + linestr->str_cur; X goto retry; X } X } X if (in_format) { X bufptr = bufend; X yylval.formval = load_format(); X in_format = FALSE; X oldoldbufptr = oldbufptr = s = str_get(linestr) + 1; X bufend = linestr->str_ptr + linestr->str_cur; X OPERATOR(FORMLIST); X } X curcmd->c_line++; X#ifdef CRYPTSCRIPT X cryptswitch(); X#endif /* CRYPTSCRIPT */ X do { X if ((s = str_gets(linestr, rsfp, 0)) == Nullch) { X fake_eof: X if (rsfp) { X if (preprocess) X (void)mypclose(rsfp); X else if (rsfp == stdin) X clearerr(stdin); X else X (void)fclose(rsfp); X rsfp = Nullfp; X } X if (minus_n || minus_p) { X str_set(linestr,minus_p ? ";}continue{print" : ""); X str_cat(linestr,";}"); X oldoldbufptr = oldbufptr = s = str_get(linestr); X bufend = linestr->str_ptr + linestr->str_cur; X minus_n = minus_p = 0; X goto retry; X } X oldoldbufptr = oldbufptr = s = str_get(linestr); X str_set(linestr,""); X RETURN(';'); /* not infinite loop because rsfp is NULL now */ X } X if (doextract && *linestr->str_ptr == '#') X doextract = FALSE; X } while (doextract); X oldoldbufptr = oldbufptr = bufptr = s; X if (perldb) { X STR *str = Str_new(85,0); X X str_sset(str,linestr); X astore(stab_xarray(curcmd->c_filestab),(int)curcmd->c_line,str); X } X#ifdef DEBUG X if (firstline) { X char *showinput(); X s = showinput(); X } X#endif X bufend = linestr->str_ptr + linestr->str_cur; X if (curcmd->c_line == 1) { X if (*s == '#' && s[1] == '!') { X if (!in_eval && !instr(s,"perl") && instr(origargv[0],"perl")) { X char **newargv; X char *cmd; X X s += 2; X if (*s == ' ') X s++; X cmd = s; X while (s < bufend && !isspace(*s)) X s++; X *s++ = '\0'; X while (s < bufend && isspace(*s)) X s++; X if (s < bufend) { X Newz(899,newargv,origargc+3,char*); X newargv[1] = s; X while (s < bufend && !isspace(*s)) X s++; X *s = '\0'; X Copy(origargv+1, newargv+2, origargc+1, char*); X } X else X newargv = origargv; X newargv[0] = cmd; X execv(cmd,newargv); X fatal("Can't exec %s", cmd); X } X } X else { X while (s < bufend && isspace(*s)) X s++; X if (*s == ':') /* for csh's that have to exec sh scripts */ X s++; X } X } X goto retry; X case ' ': case '\t': case '\f': case '\r': case 013: X s++; X goto retry; X case '#': X if (preprocess && s == str_get(linestr) && X s[1] == ' ' && isdigit(s[2])) { X curcmd->c_line = atoi(s+2)-1; X for (s += 2; isdigit(*s); s++) ; X d = bufend; X while (s < d && isspace(*s)) s++; X s[strlen(s)-1] = '\0'; /* wipe out newline */ X if (*s == '"') { X s++; X s[strlen(s)-1] = '\0'; /* wipe out trailing quote */ X } X if (*s) X curcmd->c_filestab = fstab(s); X else X curcmd->c_filestab = fstab(origfilename); X oldoldbufptr = oldbufptr = s = str_get(linestr); X } X /* FALL THROUGH */ X case '\n': X if (in_eval && !rsfp) { X d = bufend; X while (s < d && *s != '\n') X s++; X if (s < d) X s++; X if (perldb) { X STR *str = Str_new(85,0); X X str_nset(str,linestr->str_ptr, s - linestr->str_ptr); X astore(stab_xarray(curcmd->c_filestab),(int)curcmd->c_line,str); X str_chop(linestr, s); X } X if (in_format) { X bufptr = s; X yylval.formval = load_format(); X in_format = FALSE; X oldoldbufptr = oldbufptr = s = bufptr + 1; X TERM(FORMLIST); X } X curcmd->c_line++; X } X else { X *s = '\0'; X bufend = s; X } X goto retry; X case '-': X if (s[1] && isalpha(s[1]) && !isalpha(s[2])) { X s++; X switch (*s++) { X case 'r': FTST(O_FTEREAD); X case 'w': FTST(O_FTEWRITE); X case 'x': FTST(O_FTEEXEC); X case 'o': FTST(O_FTEOWNED); X case 'R': FTST(O_FTRREAD); X case 'W': FTST(O_FTRWRITE); X case 'X': FTST(O_FTREXEC); X case 'O': FTST(O_FTROWNED); X case 'e': FTST(O_FTIS); X case 'z': FTST(O_FTZERO); X case 's': FTST(O_FTSIZE); X case 'f': FTST(O_FTFILE); X case 'd': FTST(O_FTDIR); X case 'l': FTST(O_FTLINK); X case 'p': FTST(O_FTPIPE); X case 'S': FTST(O_FTSOCK); X case 'u': FTST(O_FTSUID); X case 'g': FTST(O_FTSGID); X case 'k': FTST(O_FTSVTX); X case 'b': FTST(O_FTBLK); X case 'c': FTST(O_FTCHR); X case 't': FTST(O_FTTTY); X case 'T': FTST(O_FTTEXT); X case 'B': FTST(O_FTBINARY); X case 'M': stabent("\024",TRUE); FTST(O_FTMTIME); X case 'A': stabent("\024",TRUE); FTST(O_FTATIME); X case 'C': stabent("\024",TRUE); FTST(O_FTCTIME); X default: X s -= 2; X break; X } X } X tmp = *s++; X if (*s == tmp) { X s++; X RETURN(DEC); X } X if (expectterm) X OPERATOR('-'); X else X AOP(O_SUBTRACT); X case '+': X tmp = *s++; X if (*s == tmp) { X s++; X RETURN(INC); X } X if (expectterm) X OPERATOR('+'); X else X AOP(O_ADD); X X case '*': X if (expectterm) { X s = scanident(s,bufend,tokenbuf); X yylval.stabval = stabent(tokenbuf,TRUE); X TERM(STAR); X } X tmp = *s++; X if (*s == tmp) { X s++; X OPERATOR(POW); X } X MOP(O_MULTIPLY); X case '%': X if (expectterm) { X s = scanident(s,bufend,tokenbuf); X yylval.stabval = hadd(stabent(tokenbuf,TRUE)); X TERM(HSH); X } X s++; X MOP(O_MODULO); X X case '^': X case '~': X case '(': X case ',': X case ':': X case '[': X tmp = *s++; X OPERATOR(tmp); X case '{': X tmp = *s++; X if (isspace(*s) || *s == '#') X cmdline = NOLINE; /* invalidate current command line number */ X OPERATOR(tmp); X case ';': X if (curcmd->c_line < cmdline) X cmdline = curcmd->c_line; X tmp = *s++; X OPERATOR(tmp); X case ')': X case ']': X tmp = *s++; X TERM(tmp); X case '}': X tmp = *s++; X RETURN(tmp); X case '&': X s++; X tmp = *s++; X if (tmp == '&') X OPERATOR(ANDAND); X s--; X if (expectterm) { X d = bufend; X while (s < d && isspace(*s)) X s++; X if (isalpha(*s) || *s == '_' || *s == '\'') X *(--s) = '\\'; /* force next ident to WORD */ X OPERATOR(AMPER); X } X OPERATOR('&'); X case '|': X s++; X tmp = *s++; X if (tmp == '|') X OPERATOR(OROR); X s--; X OPERATOR('|'); X case '=': X s++; X tmp = *s++; X if (tmp == '=') X EOP(O_EQ); X if (tmp == '~') X OPERATOR(MATCH); X s--; X OPERATOR('='); X case '!': X s++; X tmp = *s++; X if (tmp == '=') X EOP(O_NE); X if (tmp == '~') X OPERATOR(NMATCH); X s--; X OPERATOR('!'); X case '<': X if (expectterm) { X s = scanstr(s); X TERM(RSTRING); X } X s++; X tmp = *s++; X if (tmp == '<') X OPERATOR(LS); X if (tmp == '=') { X tmp = *s++; X if (tmp == '>') X EOP(O_NCMP); X s--; X ROP(O_LE); X } X s--; X ROP(O_LT); X case '>': X s++; X tmp = *s++; X if (tmp == '>') X OPERATOR(RS); X if (tmp == '=') X ROP(O_GE); X s--; X ROP(O_GT); X X#define SNARFWORD \ X d = tokenbuf; \ X while (isascii(*s) && \ X (isalpha(*s) || isdigit(*s) || *s == '_' || *s == '\'')) \ X *d++ = *s++; \ X while (d[-1] == '\'') \ X d--,s--; \ X *d = '\0'; \ X d = tokenbuf; X X case '$': X if (s[1] == '#' && (isalpha(s[2]) || s[2] == '_')) { X s++; X s = scanident(s,bufend,tokenbuf); X yylval.stabval = aadd(stabent(tokenbuf,TRUE)); X TERM(ARYLEN); X } X d = s; X s = scanident(s,bufend,tokenbuf); X if (reparse) { /* turn ${foo[bar]} into ($foo[bar]) */ X do_reparse: X s[-1] = ')'; X s = d; X s[1] = s[0]; X s[0] = '('; X goto retry; X } X yylval.stabval = stabent(tokenbuf,TRUE); X TERM(REG); X X case '@': X d = s; X s = scanident(s,bufend,tokenbuf); X if (reparse) X goto do_reparse; X yylval.stabval = aadd(stabent(tokenbuf,TRUE)); X TERM(ARY); X X case '/': /* may either be division or pattern */ X case '?': /* may either be conditional or pattern */ X if (expectterm) { X s = scanpat(s); X TERM(PATTERN); X } X tmp = *s++; X if (tmp == '/') X MOP(O_DIVIDE); X OPERATOR(tmp); X X case '.': X if (!expectterm || !isdigit(s[1])) { X tmp = *s++; X if (*s == tmp) { X s++; X OPERATOR(DOTDOT); X } X AOP(O_CONCAT); X } X /* FALL THROUGH */ X case '0': case '1': case '2': case '3': case '4': X case '5': case '6': case '7': case '8': case '9': X case '\'': case '"': case '`': X s = scanstr(s); X TERM(RSTRING); X X case '\\': /* some magic to force next word to be a WORD */ X s++; /* used by do and sub to force a separate namespace */ X /* FALL THROUGH */ X case '_': X SNARFWORD; X if (d[1] == '_') { X if (strEQ(d,"__LINE__") || strEQ(d,"__FILE__")) { X ARG *arg = op_new(1); X X yylval.arg = arg; X arg->arg_type = O_ITEM; X if (d[2] == 'L') X (void)sprintf(tokenbuf,"%ld",(long)curcmd->c_line); X else X strcpy(tokenbuf, stab_val(curcmd->c_filestab)->str_ptr); X arg[1].arg_type = A_SINGLE; X arg[1].arg_ptr.arg_str = str_make(tokenbuf,strlen(tokenbuf)); X TERM(RSTRING); X } X else if (strEQ(d,"__END__")) { X#ifndef TAINT X STAB *stab; X int fd; X X if (stab = stabent("DATA",FALSE)) { X stab->str_pok |= SP_MULTI; X stab_io(stab) = stio_new(); X stab_io(stab)->ifp = rsfp; X#if defined(HAS_FCNTL) && defined(F_SETFD) X fd = fileno(rsfp); X fcntl(fd,F_SETFD,fd >= 3); X#endif X if (preprocess) X stab_io(stab)->type = '|'; X else if (rsfp == stdin) X stab_io(stab)->type = '-'; X else X stab_io(stab)->type = '<'; X rsfp = Nullfp; X } X#endif X goto fake_eof; X } X } X break; X case 'a': case 'A': X SNARFWORD; X if (strEQ(d,"alarm")) X UNI(O_ALARM); X if (strEQ(d,"accept")) X FOP22(O_ACCEPT); X if (strEQ(d,"atan2")) X FUN2(O_ATAN2); X break; X case 'b': case 'B': X SNARFWORD; X if (strEQ(d,"bind")) X FOP2(O_BIND); X if (strEQ(d,"binmode")) X FOP(O_BINMODE); X break; X case 'c': case 'C': X SNARFWORD; X if (strEQ(d,"chop")) X LFUN(O_CHOP); X if (strEQ(d,"continue")) X OPERATOR(CONTINUE); X if (strEQ(d,"chdir")) { X (void)stabent("ENV",TRUE); /* may use HOME */ X UNI(O_CHDIR); X } X if (strEQ(d,"close")) X FOP(O_CLOSE); X if (strEQ(d,"closedir")) X FOP(O_CLOSEDIR); X if (strEQ(d,"cmp")) X EOP(O_SCMP); X if (strEQ(d,"caller")) X UNI(O_CALLER); X if (strEQ(d,"crypt")) { X#ifdef FCRYPT X init_des(); X#endif X FUN2(O_CRYPT); X } X if (strEQ(d,"chmod")) X LOP(O_CHMOD); X if (strEQ(d,"chown")) X LOP(O_CHOWN); X if (strEQ(d,"connect")) X FOP2(O_CONNECT); X if (strEQ(d,"cos")) X UNI(O_COS); X if (strEQ(d,"chroot")) X UNI(O_CHROOT); X break; X case 'd': case 'D': X SNARFWORD; X if (strEQ(d,"do")) { X d = bufend; X while (s < d && isspace(*s)) X s++; X if (isalpha(*s) || *s == '_') X *(--s) = '\\'; /* force next ident to WORD */ X OPERATOR(DO); X } X if (strEQ(d,"die")) X LOP(O_DIE); X if (strEQ(d,"defined")) X LFUN(O_DEFINED); X if (strEQ(d,"delete")) X OPERATOR(DELETE); X if (strEQ(d,"dbmopen")) X HFUN3(O_DBMOPEN); X if (strEQ(d,"dbmclose")) X HFUN(O_DBMCLOSE); X if (strEQ(d,"dump")) X LOOPX(O_DUMP); X break; X case 'e': case 'E': X SNARFWORD; X if (strEQ(d,"else")) X OPERATOR(ELSE); X if (strEQ(d,"elsif")) { X yylval.ival = curcmd->c_line; X OPERATOR(ELSIF); X } X if (strEQ(d,"eq") || strEQ(d,"EQ")) X EOP(O_SEQ); X if (strEQ(d,"exit")) X UNI(O_EXIT); X if (strEQ(d,"eval")) { X allstabs = TRUE; /* must initialize everything since */ X UNI(O_EVAL); /* we don't know what will be used */ X } X if (strEQ(d,"eof")) X FOP(O_EOF); X if (strEQ(d,"exp")) X UNI(O_EXP); X if (strEQ(d,"each")) X HFUN(O_EACH); X if (strEQ(d,"exec")) { X set_csh(); X LOP(O_EXEC_OP); X } X if (strEQ(d,"endhostent")) X FUN0(O_EHOSTENT); X if (strEQ(d,"endnetent")) X FUN0(O_ENETENT); X if (strEQ(d,"endservent")) X FUN0(O_ESERVENT); X if (strEQ(d,"endprotoent")) X FUN0(O_EPROTOENT); X if (strEQ(d,"endpwent")) X FUN0(O_EPWENT); X if (strEQ(d,"endgrent")) X FUN0(O_EGRENT); X break; X case 'f': case 'F': X SNARFWORD; X if (strEQ(d,"for") || strEQ(d,"foreach")) { X yylval.ival = curcmd->c_line; X OPERATOR(FOR); X } X if (strEQ(d,"format")) { X d = bufend; X while (s < d && isspace(*s)) X s++; X if (isalpha(*s) || *s == '_') X *(--s) = '\\'; /* force next ident to WORD */ X in_format = TRUE; X allstabs = TRUE; /* must initialize everything since */ X OPERATOR(FORMAT); /* we don't know what will be used */ X } X if (strEQ(d,"fork")) X FUN0(O_FORK); X if (strEQ(d,"fcntl")) X FOP3(O_FCNTL); X if (strEQ(d,"fileno")) X FOP(O_FILENO); X if (strEQ(d,"flock")) X FOP2(O_FLOCK); X break; X case 'g': case 'G': X SNARFWORD; X if (strEQ(d,"gt") || strEQ(d,"GT")) X ROP(O_SGT); X if (strEQ(d,"ge") || strEQ(d,"GE")) X ROP(O_SGE); X if (strEQ(d,"grep")) X FL2(O_GREP); X if (strEQ(d,"goto")) X LOOPX(O_GOTO); X if (strEQ(d,"gmtime")) X UNI(O_GMTIME); X if (strEQ(d,"getc")) X FOP(O_GETC); X if (strnEQ(d,"get",3)) { X d += 3; X if (*d == 'p') { X if (strEQ(d,"ppid")) X FUN0(O_GETPPID); X if (strEQ(d,"pgrp")) X UNI(O_GETPGRP); X if (strEQ(d,"priority")) X FUN2(O_GETPRIORITY); X if (strEQ(d,"protobyname")) X UNI(O_GPBYNAME); X if (strEQ(d,"protobynumber")) X FUN1(O_GPBYNUMBER); X if (strEQ(d,"protoent")) X FUN0(O_GPROTOENT); X if (strEQ(d,"pwent")) X FUN0(O_GPWENT); X if (strEQ(d,"pwnam")) X FUN1(O_GPWNAM); X if (strEQ(d,"pwuid")) X FUN1(O_GPWUID); X if (strEQ(d,"peername")) X FOP(O_GETPEERNAME); X } X else if (*d == 'h') { X if (strEQ(d,"hostbyname")) X UNI(O_GHBYNAME); X if (strEQ(d,"hostbyaddr")) X FUN2(O_GHBYADDR); X if (strEQ(d,"hostent")) X FUN0(O_GHOSTENT); X } X else if (*d == 'n') { X if (strEQ(d,"netbyname")) X UNI(O_GNBYNAME); X if (strEQ(d,"netbyaddr")) X FUN2(O_GNBYADDR); X if (strEQ(d,"netent")) X FUN0(O_GNETENT); X } X else if (*d == 's') { X if (strEQ(d,"servbyname")) X FUN2(O_GSBYNAME); X if (strEQ(d,"servbyport")) X FUN2(O_GSBYPORT); X if (strEQ(d,"servent")) X FUN0(O_GSERVENT); X if (strEQ(d,"sockname")) X FOP(O_GETSOCKNAME); X if (strEQ(d,"sockopt")) X FOP3(O_GSOCKOPT); X } X else if (*d == 'g') { X if (strEQ(d,"grent")) X FUN0(O_GGRENT); X if (strEQ(d,"grnam")) X FUN1(O_GGRNAM); X if (strEQ(d,"grgid")) X FUN1(O_GGRGID); X } X else if (*d == 'l') { X if (strEQ(d,"login")) X FUN0(O_GETLOGIN); X } X d -= 3; X } X break; X case 'h': case 'H': X SNARFWORD; X if (strEQ(d,"hex")) X UNI(O_HEX); X break; X case 'i': case 'I': X SNARFWORD; X if (strEQ(d,"if")) { X yylval.ival = curcmd->c_line; X OPERATOR(IF); X } X if (strEQ(d,"index")) X FUN2x(O_INDEX); X if (strEQ(d,"int")) X UNI(O_INT); X if (strEQ(d,"ioctl")) X FOP3(O_IOCTL); X break; X case 'j': case 'J': X SNARFWORD; X if (strEQ(d,"join")) X FL2(O_JOIN); X break; X case 'k': case 'K': X SNARFWORD; X if (strEQ(d,"keys")) X HFUN(O_KEYS); X if (strEQ(d,"kill")) X LOP(O_KILL); X break; X case 'l': case 'L': X SNARFWORD; X if (strEQ(d,"last")) X LOOPX(O_LAST); X if (strEQ(d,"local")) X OPERATOR(LOCAL); X if (strEQ(d,"length")) X UNI(O_LENGTH); X if (strEQ(d,"lt") || strEQ(d,"LT")) X ROP(O_SLT); X if (strEQ(d,"le") || strEQ(d,"LE")) X ROP(O_SLE); X if (strEQ(d,"localtime")) X UNI(O_LOCALTIME); X if (strEQ(d,"log")) X UNI(O_LOG); X if (strEQ(d,"link")) X FUN2(O_LINK); X if (strEQ(d,"listen")) X FOP2(O_LISTEN); X if (strEQ(d,"lstat")) X FOP(O_LSTAT); X break; X case 'm': case 'M': X if (s[1] == '\'') { X d = "m"; X s++; X } X else { X SNARFWORD; X } X if (strEQ(d,"m")) { X s = scanpat(s-1); X if (yylval.arg) X TERM(PATTERN); X else X RETURN(1); /* force error */ X } X switch (d[1]) { X case 'k': X if (strEQ(d,"mkdir")) X FUN2(O_MKDIR); X break; X case 's': X if (strEQ(d,"msgctl")) X FUN3(O_MSGCTL); X if (strEQ(d,"msgget")) X FUN2(O_MSGGET); X if (strEQ(d,"msgrcv")) X FUN5(O_MSGRCV); X if (strEQ(d,"msgsnd")) X FUN3(O_MSGSND); X break; X } X break; X case 'n': case 'N': X SNARFWORD; X if (strEQ(d,"next")) X LOOPX(O_NEXT); X if (strEQ(d,"ne") || strEQ(d,"NE")) X EOP(O_SNE); X break; X case 'o': case 'O': X SNARFWORD; X if (strEQ(d,"open")) X OPERATOR(OPEN); X if (strEQ(d,"ord")) X UNI(O_ORD); X if (strEQ(d,"oct")) X UNI(O_OCT); X if (strEQ(d,"opendir")) X FOP2(O_OPENDIR); X break; X case 'p': case 'P': X SNARFWORD; X if (strEQ(d,"print")) { X checkcomma(s,"filehandle"); X LOP(O_PRINT); X } X if (strEQ(d,"printf")) { X checkcomma(s,"filehandle"); X LOP(O_PRTF); X } X if (strEQ(d,"push")) { X yylval.ival = O_PUSH; X OPERATOR(PUSH); X } X if (strEQ(d,"pop")) X OPERATOR(POP); X if (strEQ(d,"pack")) X FL2(O_PACK); X if (strEQ(d,"package")) X OPERATOR(PACKAGE); X if (strEQ(d,"pipe")) X FOP22(O_PIPE); X break; X case 'q': case 'Q': X SNARFWORD; X if (strEQ(d,"q")) { X s = scanstr(s-1); X TERM(RSTRING); X } X if (strEQ(d,"qq")) { X s = scanstr(s-2); X TERM(RSTRING); X } X if (strEQ(d,"qx")) { X s = scanstr(s-2); X TERM(RSTRING); X } X break; X case 'r': case 'R': X SNARFWORD; X if (strEQ(d,"return")) X OLDLOP(O_RETURN); X if (strEQ(d,"require")) { X allstabs = TRUE; /* must initialize everything since */ X UNI(O_REQUIRE); /* we don't know what will be used */ X } X if (strEQ(d,"reset")) X UNI(O_RESET); X if (strEQ(d,"redo")) X LOOPX(O_REDO); X if (strEQ(d,"rename")) X FUN2(O_RENAME); X if (strEQ(d,"rand")) X UNI(O_RAND); X if (strEQ(d,"rmdir")) X UNI(O_RMDIR); X if (strEQ(d,"rindex")) X FUN2x(O_RINDEX); X if (strEQ(d,"read")) X FOP3(O_READ); X if (strEQ(d,"readdir")) X FOP(O_READDIR); X if (strEQ(d,"rewinddir")) X FOP(O_REWINDDIR); X if (strEQ(d,"recv")) X FOP4(O_RECV); X if (strEQ(d,"reverse")) X LOP(O_REVERSE); X if (strEQ(d,"readlink")) X UNI(O_READLINK); X break; X case 's': case 'S': X if (s[1] == '\'') { X d = "s"; X s++; X } X else { X SNARFWORD; X } X if (strEQ(d,"s")) { X s = scansubst(s); X if (yylval.arg) X TERM(SUBST); X else X RETURN(1); /* force error */ X } X switch (d[1]) { X case 'a': X case 'b': X break; X case 'c': X if (strEQ(d,"scalar")) X UNI(O_SCALAR); X break; X case 'd': X break; X case 'e': X if (strEQ(d,"select")) X OPERATOR(SSELECT); X if (strEQ(d,"seek")) X FOP3(O_SEEK); X if (strEQ(d,"semctl")) X FUN4(O_SEMCTL); X if (strEQ(d,"semget")) X FUN3(O_SEMGET); X if (strEQ(d,"semop")) X FUN2(O_SEMOP); X if (strEQ(d,"send")) X FOP3(O_SEND); X if (strEQ(d,"setpgrp")) X FUN2(O_SETPGRP); X if (strEQ(d,"setpriority")) X FUN3(O_SETPRIORITY); X if (strEQ(d,"sethostent")) X FUN1(O_SHOSTENT); X if (strEQ(d,"setnetent")) X FUN1(O_SNETENT); X if (strEQ(d,"setservent")) X FUN1(O_SSERVENT); X if (strEQ(d,"setprotoent")) X FUN1(O_SPROTOENT); X if (strEQ(d,"setpwent")) X FUN0(O_SPWENT); X if (strEQ(d,"setgrent")) X FUN0(O_SGRENT); X if (strEQ(d,"seekdir")) X FOP2(O_SEEKDIR); X if (strEQ(d,"setsockopt")) X FOP4(O_SSOCKOPT); X break; X case 'f': X case 'g': X break; X case 'h': X if (strEQ(d,"shift")) X TERM(SHIFT); X if (strEQ(d,"shmctl")) X FUN3(O_SHMCTL); X if (strEQ(d,"shmget")) X FUN3(O_SHMGET); X if (strEQ(d,"shmread")) X FUN4(O_SHMREAD); X if (strEQ(d,"shmwrite")) X FUN4(O_SHMWRITE); X if (strEQ(d,"shutdown")) X FOP2(O_SHUTDOWN); X break; X case 'i': X if (strEQ(d,"sin")) X UNI(O_SIN); X break; X case 'j': X case 'k': X break; X case 'l': X if (strEQ(d,"sleep")) X UNI(O_SLEEP); X break; X case 'm': X case 'n': X break; X case 'o': X if (strEQ(d,"socket")) X FOP4(O_SOCKET); X if (strEQ(d,"socketpair")) X FOP25(O_SOCKPAIR); X if (strEQ(d,"sort")) { X checkcomma(s,"subroutine name"); X d = bufend; X while (s < d && isascii(*s) && isspace(*s)) s++; X if (*s == ';' || *s == ')') /* probably a close */ X fatal("sort is now a reserved word"); X if (isascii(*s) && (isalpha(*s) || *s == '_')) { X for (d = s; isalpha(*d) || isdigit(*d) || *d == '_'; d++) ; X strncpy(tokenbuf,s,d-s); X if (strNE(tokenbuf,"keys") && X strNE(tokenbuf,"values") && X strNE(tokenbuf,"split") && X strNE(tokenbuf,"grep") && X strNE(tokenbuf,"readdir") && X strNE(tokenbuf,"unpack") && X strNE(tokenbuf,"do") && X (d >= bufend || isspace(*d)) ) X *(--s) = '\\'; /* force next ident to WORD */ X } X LOP(O_SORT); X } X break; X case 'p': X if (strEQ(d,"split")) X TERM(SPLIT); X if (strEQ(d,"sprintf")) X FL(O_SPRINTF); X if (strEQ(d,"splice")) { X yylval.ival = O_SPLICE; X OPERATOR(PUSH); X } X break; X case 'q': X if (strEQ(d,"sqrt")) X UNI(O_SQRT); X break; X case 'r': X if (strEQ(d,"srand")) X UNI(O_SRAND); X break; X case 's': X break; X case 't': X if (strEQ(d,"stat")) X FOP(O_STAT); X if (strEQ(d,"study")) { X sawstudy++; X LFUN(O_STUDY); X } X break; X case 'u': X if (strEQ(d,"substr")) X FUN2x(O_SUBSTR); X if (strEQ(d,"sub")) { X subline = curcmd->c_line; X d = bufend; X while (s < d && isspace(*s)) X s++; X if (isalpha(*s) || *s == '_' || *s == '\'') { X if (perldb) { X str_sset(subname,curstname); X str_ncat(subname,"'",1); X for (d = s+1; X isalpha(*d) || isdigit(*d) || *d == '_' || *d == '\''; X d++); X if (d[-1] == '\'') X d--; X str_ncat(subname,s,d-s); X } X *(--s) = '\\'; /* force next ident to WORD */ X } X else if (perldb) X str_set(subname,"?"); X OPERATOR(SUB); X } X break; X case 'v': X case 'w': X case 'x': X break; X case 'y': X if (strEQ(d,"system")) { X set_csh(); X LOP(O_SYSTEM); X } X if (strEQ(d,"symlink")) X FUN2(O_SYMLINK); X if (strEQ(d,"syscall")) X LOP(O_SYSCALL); X if (strEQ(d,"sysread")) X FOP3(O_SYSREAD); X if (strEQ(d,"syswrite")) X FOP3(O_SYSWRITE); X break; X case 'z': X break; X } X break; X case 't': case 'T': X SNARFWORD; X if (strEQ(d,"tr")) { X s = scantrans(s); X if (yylval.arg) X TERM(TRANS); X else X RETURN(1); /* force error */ X } X if (strEQ(d,"tell")) X FOP(O_TELL); X if (strEQ(d,"telldir")) X FOP(O_TELLDIR); X if (strEQ(d,"time")) X FUN0(O_TIME); X if (strEQ(d,"times")) X FUN0(O_TMS); X if (strEQ(d,"truncate")) X FOP2(O_TRUNCATE); X break; X case 'u': case 'U': X SNARFWORD; X if (strEQ(d,"using")) X OPERATOR(USING); X if (strEQ(d,"until")) { X yylval.ival = curcmd->c_line; X OPERATOR(UNTIL); X } X if (strEQ(d,"unless")) { X yylval.ival = curcmd->c_line; X OPERATOR(UNLESS); X } X if (strEQ(d,"unlink")) X LOP(O_UNLINK); X if (strEQ(d,"undef")) X LFUN(O_UNDEF); X if (strEQ(d,"unpack")) X FUN2(O_UNPACK); X if (strEQ(d,"utime")) X LOP(O_UTIME); X if (strEQ(d,"umask")) X UNI(O_UMASK); X if (strEQ(d,"unshift")) { X yylval.ival = O_UNSHIFT; X OPERATOR(PUSH); X } X break; X case 'v': case 'V': X SNARFWORD; X if (strEQ(d,"values")) X HFUN(O_VALUES); X if (strEQ(d,"vec")) { X sawvec = TRUE; X FUN3(O_VEC); X } X break; X case 'w': case 'W': X SNARFWORD; X if (strEQ(d,"while")) { X yylval.ival = curcmd->c_line; X OPERATOR(WHILE); X } X if (strEQ(d,"warn")) X LOP(O_WARN); X if (strEQ(d,"wait")) X FUN0(O_WAIT); X if (strEQ(d,"waitpid")) X FUN2(O_WAITPID); X if (strEQ(d,"wantarray")) { X yylval.arg = op_new(1); X yylval.arg->arg_type = O_ITEM; X yylval.arg[1].arg_type = A_WANTARRAY; X TERM(RSTRING); X } X if (strEQ(d,"write")) X FOP(O_WRITE); X break; X case 'x': case 'X': X SNARFWORD; X if (!expectterm && strEQ(d,"x")) X MOP(O_REPEAT); X break; X case 'y': case 'Y': X if (s[1] == '\'') { X d = "y"; X s++; X } X else { X SNARFWORD; X } X if (strEQ(d,"y")) { X s = scantrans(s); X TERM(TRANS); X } X break; X case 'z': case 'Z': X SNARFWORD; X break; X } X yylval.cval = savestr(d); X expectterm = FALSE; X if (oldoldbufptr && oldoldbufptr < bufptr) { X while (isspace(*oldoldbufptr)) X oldoldbufptr++; X if (*oldoldbufptr == 'p' && strnEQ(oldoldbufptr,"print",5)) X expectterm = TRUE; X else if (*oldoldbufptr == 's' && strnEQ(oldoldbufptr,"sort",4)) X expectterm = TRUE; X } X return (CLINE, bufptr = s, (int)WORD); X} X Xvoid Xcheckcomma(s,what) Xregister char *s; Xchar *what; X{ X char *someword; X X if (*s == '(') X s++; X while (s < bufend && isascii(*s) && isspace(*s)) X s++; X if (isascii(*s) && (isalpha(*s) || *s == '_')) { X someword = s++; X while (isalpha(*s) || isdigit(*s) || *s == '_') X s++; X while (s < bufend && isspace(*s)) X s++; X if (*s == ',') { X *s = '\0'; X someword = instr( X "tell eof times getlogin wait length shift umask getppid \ X cos exp int log rand sin sqrt ord wantarray", X someword); X *s = ','; X if (someword) X return; X fatal("No comma allowed after %s", what); X } X } X} X Xchar * Xscanident(s,send,dest) Xregister char *s; Xregister char *send; Xchar *dest; X{ X register char *d; X int brackets = 0; X X reparse = Nullch; X s++; X d = dest; X if (isdigit(*s)) { X while (isdigit(*s)) X *d++ = *s++; X } X else { X while (isalpha(*s) || isdigit(*s) || *s == '_' || *s == '\'') X *d++ = *s++; X } X while (d > dest+1 && d[-1] == '\'') X d--,s--; X *d = '\0'; X d = dest; X if (!*d) { X *d = *s++; X if (*d == '{' /* } */ ) { X d = dest; X brackets++; X while (s < send && brackets) { X if (!reparse && (d == dest || (*s && isascii(*s) && X (isalpha(*s) || isdigit(*s) || *s == '_') ))) { X *d++ = *s++; X continue; X } X else if (!reparse) X reparse = s; X switch (*s++) { X /* { */ X case '}': X brackets--; X if (reparse && reparse == s - 1) X reparse = Nullch; X break; X case '{': /* } */ X brackets++; X break; X } X } X *d = '\0'; X d = dest; X } X else X d[1] = '\0'; X } X if (*d == '^' && (isupper(*s) || index("[\\]^_?",*s))) X *d = *s++ ^ 64; X return s; X} X XSTR * Xscanconst(string,len) Xchar *string; Xint len; X{ X register STR *retstr; X register char *t; X register char *d; X register char *e; X X if (index(string,'|')) { X return Nullstr; X } X retstr = Str_new(86,len); X str_nset(retstr,string,len); X t = str_get(retstr); X e = t + len; X retstr->str_u.str_useful = 100; X for (d=t; d < e; ) { X switch (*d) { X case '{': X if (isdigit(d[1])) X e = d; X else X goto defchar; X break; X case '.': case '[': case '$': case '(': case ')': case '|': case '+': X e = d; X break; X case '\\': X if (d[1] && index("wWbB0123456789sSdDlLuUE",d[1])) { X e = d; X break; X } X (void)bcopy(d+1,d,e-d); X e--; X switch(*d) { X case 'n': X *d = '\n'; X break; X case 't': X *d = '\t'; X break; X case 'f': X *d = '\f'; X break; X case 'r': X *d = '\r'; X break; X case 'e': X *d = '\033'; X break; X case 'a': X *d = '\007'; X break; X } X /* FALL THROUGH */ X default: X defchar: X if (d[1] == '*' || (d[1] == '{' && d[2] == '0') || d[1] == '?') { X e = d; X break; X } X d++; X } X } X if (d == t) { X str_free(retstr); X return Nullstr; X } X *d = '\0'; X retstr->str_cur = d - t; X return retstr; X} X Xchar * Xscanpat(s) Xregister char *s; X{ X register SPAT *spat; X register char *d; X register char *e; X int len; X SPAT savespat; X STR *str = Str_new(93,0); X X Newz(801,spat,1,SPAT); X spat->spat_next = curstash->tbl_spatroot; /* link into spat list */ X curstash->tbl_spatroot = spat; X X switch (*s++) { X case 'm': X s++; X break; X case '/': X break; X case '?': X spat->spat_flags |= SPAT_ONCE; X break; X default: X fatal("panic: scanpat"); X } X s = str_append_till(str,s,bufend,s[-1],patleave); X if (s >= bufend) { X str_free(str); X yyerror("Search pattern not terminated"); X yylval.arg = Nullarg; X return s; X } X s++; X while (*s == 'i' || *s == 'o') { X if (*s == 'i') { X s++; X sawi = TRUE; X spat->spat_flags |= SPAT_FOLD; X } X if (*s == 'o') { X s++; X spat->spat_flags |= SPAT_KEEP; X } X } X len = str->str_cur; X e = str->str_ptr + len; X for (d = str->str_ptr; d < e; d++) { X if (*d == '\\') X d++; X else if ((*d == '$' && d[1] && d[1] != '|' && d[1] != ')') || X (*d == '@')) { X register ARG *arg; X X spat->spat_runtime = arg = op_new(1); X arg->arg_type = O_ITEM; X arg[1].arg_type = A_DOUBLE; X arg[1].arg_ptr.arg_str = str_smake(str); X d = scanident(d,bufend,buf); X (void)stabent(buf,TRUE); /* make sure it's created */ X for (; d < e; d++) { X if (*d == '\\') X d++; X else if (*d == '$' && d[1] && d[1] != '|' && d[1] != ')') { X d = scanident(d,bufend,buf); X (void)stabent(buf,TRUE); X } X else if (*d == '@') { X d = scanident(d,bufend,buf); X if (strEQ(buf,"ARGV") || strEQ(buf,"ENV") || X strEQ(buf,"SIG") || strEQ(buf,"INC")) X (void)stabent(buf,TRUE); X } X } X goto got_pat; /* skip compiling for now */ X } X } X if (spat->spat_flags & SPAT_FOLD) X#ifdef STRUCTCOPY X savespat = *spat; X#else X (void)bcopy((char *)spat, (char *)&savespat, sizeof(SPAT)); X#endif X if (*str->str_ptr == '^') { X spat->spat_short = scanconst(str->str_ptr+1,len-1); X if (spat->spat_short) { X spat->spat_slen = spat->spat_short->str_cur; X if (spat->spat_slen == len - 1) X spat->spat_flags |= SPAT_ALL; X } X } X else { X spat->spat_flags |= SPAT_SCANFIRST; X spat->spat_short = scanconst(str->str_ptr,len); X if (spat->spat_short) { X spat->spat_slen = spat->spat_short->str_cur; X if (spat->spat_slen == len) X spat->spat_flags |= SPAT_ALL; X } X } X if ((spat->spat_flags & SPAT_ALL) && (spat->spat_flags & SPAT_SCANFIRST)) { X fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD); X spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len, X spat->spat_flags & SPAT_FOLD); X /* Note that this regexp can still be used if someone says X * something like /a/ && s//b/; so we can't delete it. X */ X } X else { X if (spat->spat_flags & SPAT_FOLD) X#ifdef STRUCTCOPY X *spat = savespat; X#else X (void)bcopy((char *)&savespat, (char *)spat, sizeof(SPAT)); X#endif X if (spat->spat_short) X fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD); X spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len, X spat->spat_flags & SPAT_FOLD); X hoistmust(spat); X } X got_pat: X str_free(str); X yylval.arg = make_match(O_MATCH,stab2arg(A_STAB,defstab),spat); X return s; X} X Xchar * Xscansubst(s) Xregister char *s; X{ X register SPAT *spat; X register char *d; X register char *e; X int len; X STR *str = Str_new(93,0); X X Newz(802,spat,1,SPAT); X spat->spat_next = curstash->tbl_spatroot; /* link into spat list */ X curstash->tbl_spatroot = spat; X X s = str_append_till(str,s+1,bufend,*s,patleave); X if (s >= bufend) { X str_free(str); X yyerror("Substitution pattern not terminated"); X yylval.arg = Nullarg; X return s; X } X len = str->str_cur; X e = str->str_ptr + len; X for (d = str->str_ptr; d < e; d++) { X if (*d == '\\') X d++; X else if ((*d == '$' && d[1] && d[1] != '|' && /*(*/ d[1] != ')') || X *d == '@' ) { X register ARG *arg; X X spat->spat_runtime = arg = op_new(1); X arg->arg_type = O_ITEM; X arg[1].arg_type = A_DOUBLE; X arg[1].arg_ptr.arg_str = str_smake(str); X d = scanident(d,bufend,buf); X (void)stabent(buf,TRUE); /* make sure it's created */ X for (; *d; d++) { X if (*d == '$' && d[1] && d[-1] != '\\' && d[1] != '|') { X d = scanident(d,bufend,buf); X (void)stabent(buf,TRUE); X } X else if (*d == '@' && d[-1] != '\\') { X d = scanident(d,bufend,buf); X if (strEQ(buf,"ARGV") || strEQ(buf,"ENV") || X strEQ(buf,"SIG") || strEQ(buf,"INC")) X (void)stabent(buf,TRUE); X } X } X goto get_repl; /* skip compiling for now */ X } X } X if (*str->str_ptr == '^') { X spat->spat_short = scanconst(str->str_ptr+1,len-1); X if (spat->spat_short) X spat->spat_slen = spat->spat_short->str_cur; X } X else { X spat->spat_flags |= SPAT_SCANFIRST; X spat->spat_short = scanconst(str->str_ptr,len); X if (spat->spat_short) X spat->spat_slen = spat->spat_short->str_cur; X } Xget_repl: X s = scanstr(s); X if (s >= bufend) { X str_free(str); X yyerror("Substitution replacement not terminated"); X yylval.arg = Nullarg; X return s; X } X spat->spat_repl = yylval.arg; X spat->spat_flags |= SPAT_ONCE; X if ((spat->spat_repl[1].arg_type & A_MASK) == A_SINGLE) X spat->spat_flags |= SPAT_CONST; X else if ((spat->spat_repl[1].arg_type & A_MASK) == A_DOUBLE) { X STR *tmpstr; X register char *t; X X spat->spat_flags |= SPAT_CONST; X tmpstr = spat->spat_repl[1].arg_ptr.arg_str; X e = tmpstr->str_ptr + tmpstr->str_cur; X for (t = tmpstr->str_ptr; t < e; t++) { X if (*t == '$' && t[1] && (index("`'&+0123456789",t[1]) || X (t[1] == '{' /*}*/ && isdigit(t[2])) )) X spat->spat_flags &= ~SPAT_CONST; X } X } X while (*s == 'g' || *s == 'i' || *s == 'e' || *s == 'o') { X if (*s == 'e') { X s++; X if ((spat->spat_repl[1].arg_type & A_MASK) == A_DOUBLE) X spat->spat_repl[1].arg_type = A_SINGLE; X spat->spat_repl = make_op(O_EVAL,2, X spat->spat_repl, X Nullarg, X Nullarg); X spat->spat_flags &= ~SPAT_CONST; X } X if (*s == 'g') { X s++; X spat->spat_flags &= ~SPAT_ONCE; X } X if (*s == 'i') { X s++; X sawi = TRUE; X spat->spat_flags |= SPAT_FOLD; X if (!(spat->spat_flags & SPAT_SCANFIRST)) { X str_free(spat->spat_short); /* anchored opt doesn't do */ X spat->spat_short = Nullstr; /* case insensitive match */ X spat->spat_slen = 0; X } X } X if (*s == 'o') { X s++; X spat->spat_flags |= SPAT_KEEP; X } X } X if (spat->spat_short && (spat->spat_flags & SPAT_SCANFIRST)) X fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD); X if (!spat->spat_runtime) { X spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len, X spat->spat_flags & SPAT_FOLD); X hoistmust(spat); X } X yylval.arg = make_match(O_SUBST,stab2arg(A_STAB,defstab),spat); X str_free(str); X return s; X} X Xhoistmust(spat) Xregister SPAT *spat; X{ X if (spat->spat_regexp->regmust) { /* is there a better short-circuit? */ X if (spat->spat_short && X str_eq(spat->spat_short,spat->spat_regexp->regmust)) X { X if (spat->spat_flags & SPAT_SCANFIRST) { X str_free(spat->spat_short); X spat->spat_short = Nullstr; X } X else { X str_free(spat->spat_regexp->regmust); X spat->spat_regexp->regmust = Nullstr; X return; X } X } X if (!spat->spat_short || /* promote the better string */ X ((spat->spat_flags & SPAT_SCANFIRST) && X (spat->spat_short->str_cur < spat->spat_regexp->regmust->str_cur) )){ X str_free(spat->spat_short); /* ok if null */ X spat->spat_short = spat->spat_regexp->regmust; X spat->spat_regexp->regmust = Nullstr; X spat->spat_flags |= SPAT_SCANFIRST; X } X } X} X Xchar * Xexpand_charset(s,len,retlen) Xregister char *s; Xint len; Xint *retlen; X{ X char t[520]; X register char *d = t; X register int i; X register char *send = s + len; X X while (s < send && d - t <= 256) { X if (s[1] == '-' && s+2 < send) { X for (i = (s[0] & 0377); i <= (s[2] & 0377); i++) X *d++ = i; X s += 3; X } X else X *d++ = *s++; X } X *d = '\0'; X *retlen = d - t; X return nsavestr(t,d-t); X} X Xchar * Xscantrans(s) Xregister char *s; X{ X ARG *arg = X l(make_op(O_TRANS,2,stab2arg(A_STAB,defstab),Nullarg,Nullarg)); X register char *t; X register char *r; X register short *tbl; X register int i; X register int j; X int tlen, rlen; X int squash; X int delete; X int complement; X X New(803,tbl,256,short); X arg[2].arg_type = A_NULL; X arg[2].arg_ptr.arg_cval = (char*) tbl; X s = scanstr(s); X if (s >= bufend) { X yyerror("Translation pattern not terminated"); X yylval.arg = Nullarg; X return s; X } X t = expand_charset(yylval.arg[1].arg_ptr.arg_str->str_ptr, X yylval.arg[1].arg_ptr.arg_str->str_cur,&tlen); X arg_free(yylval.arg); X s = scanstr(s-1); X if (s >= bufend) { X yyerror("Translation replacement not terminated"); X yylval.arg = Nullarg; X return s; X } X complement = delete = squash = 0; X while (*s == 'c' || *s == 'd' || *s == 's') { X if (*s == 'c') X complement = 1; X else if (*s == 'd') X delete = 2; X else X squash = 1; X s++; X } X r = expand_charset(yylval.arg[1].arg_ptr.arg_str->str_ptr, X yylval.arg[1].arg_ptr.arg_str->str_cur,&rlen); X arg_free(yylval.arg); X arg[2].arg_len = delete|squash; X yylval.arg = arg; X if (!rlen && !delete) { X Safefree(r); X r = t; rlen = tlen; X } X if (complement) { X Zero(tbl, 256, short); X for (i = 0; i < tlen; i++) X tbl[t[i] & 0377] = -1; X for (i = 0, j = 0; i < 256; i++) { X if (!tbl[i]) { X if (j >= rlen) { X if (delete) X tbl[i] = -2; X else X tbl[i] = r[j-1]; X } X else X tbl[i] = r[j++]; X } X } X } X else { X for (i = 0; i < 256; i++) X tbl[i] = -1; X for (i = 0, j = 0; i < tlen; i++,j++) { X if (j >= rlen) { X if (delete) { X if (tbl[t[i] & 0377] == -1) X tbl[t[i] & 0377] = -2; X continue; X } X --j; X } X if (tbl[t[i] & 0377] == -1) X tbl[t[i] & 0377] = r[j] & 0377; X } X } X if (r != t) X Safefree(r); X Safefree(t); X return s; X} X Xchar * Xscanstr(s) Xregister char *s; X{ X register char term; X register char *d; X register ARG *arg; X register char *send; X register bool makesingle = FALSE; X register STAB *stab; X bool alwaysdollar = FALSE; X bool hereis = FALSE; X STR *herewas; X STR *str; X char *leave = "\\$@nrtfbeacx0123456789[{]}lLuUE"; /* which backslash sequences to keep */ X int len; X X arg = op_new(1); X yylval.arg = arg; X arg->arg_type = O_ITEM; X X switch (*s) { X default: /* a substitution replacement */ X arg[1].arg_type = A_DOUBLE; X makesingle = TRUE; /* maybe disable runtime scanning */ X term = *s; X if (term == '\'') X leave = Nullch; X goto snarf_it; X case '0': X { X unsigned long i; X int shift; X X arg[1].arg_type = A_SINGLE; X if (s[1] == 'x') { X shift = 4; X s += 2; X } X else if (s[1] == '.') X goto decimal; X else X shift = 3; X i = 0; X for (;;) { X switch (*s) { X default: X goto out; X case '8': case '9': X if (shift != 4) X yyerror("Illegal octal digit"); X /* FALL THROUGH */ X case '0': case '1': case '2': case '3': case '4': X case '5': case '6': case '7': X i <<= shift; X i += *s++ & 15; X break; X case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': X case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': X if (shift != 4) X goto out; X i <<= 4; X i += (*s++ & 7) + 9; X break; X } X } X out: X str = Str_new(92,0); X str_numset(str,(double)i); X if (str->str_ptr) { X Safefree(str->str_ptr); X str->str_ptr = Nullch; X str->str_len = str->str_cur = 0; X } X arg[1].arg_ptr.arg_str = str; X } X break; X case '1': case '2': case '3': case '4': case '5': X case '6': case '7': case '8': case '9': case '.': X decimal: X arg[1].arg_type = A_SINGLE; X d = tokenbuf; X while (isdigit(*s) || *s == '_') { X if (*s == '_') X s++; X else X *d++ = *s++; X } X if (*s == '.' && s[1] && index("0123456789eE ;",s[1])) { X *d++ = *s++; X while (isdigit(*s) || *s == '_') { X if (*s == '_') X s++; X else X *d++ = *s++; X } X } X if (*s && index("eE",*s) && index("+-0123456789",s[1])) { X *d++ = *s++; X if (*s == '+' || *s == '-') X *d++ = *s++; X while (isdigit(*s)) X *d++ = *s++; X } X *d = '\0'; X str = Str_new(92,0); X str_numset(str,atof(tokenbuf)); X if (str->str_ptr) { X Safefree(str->str_ptr); X str->str_ptr = Nullch; X str->str_len = str->str_cur = 0; X } X arg[1].arg_ptr.arg_str = str; X break; X case '<': X if (*++s == '<') { X hereis = TRUE; X d = tokenbuf; X if (!rsfp) X *d++ = '\n'; X if (*++s && index("`'\"",*s)) { X term = *s++; X s = cpytill(d,s,bufend,term,&len); X if (s < bufend) X s++; X d += len; X } X else { X if (*s == '\\') X s++, term = '\''; X else X term = '"'; X while (isascii(*s) && (isalpha(*s) || isdigit(*s) || *s == '_')) X *d++ = *s++; X } /* assuming tokenbuf won't clobber */ X *d++ = '\n'; X *d = '\0'; X len = d - tokenbuf; X d = "\n"; X if (rsfp || !(d=ninstr(s,bufend,d,d+1))) X herewas = str_make(s,bufend-s); X else X s--, herewas = str_make(s,d-s); X s += herewas->str_cur; X if (term == '\'') X goto do_single; X if (term == '`') X goto do_back; X goto do_double; X } X d = tokenbuf; X s = cpytill(d,s,bufend,'>',&len); X if (s < bufend) X s++; X if (*d == '$') d++; X while (*d && X (isalpha(*d) || isdigit(*d) || *d == '_' || *d == '\'')) X d++; X if (d - tokenbuf != len) { X d = tokenbuf; X arg[1].arg_type = A_GLOB; X d = nsavestr(d,len); X arg[1].arg_ptr.arg_stab = stab = genstab(); X stab_io(stab) = stio_new(); X stab_val(stab) = str_make(d,len); X Safefree(d); X set_csh(); X } X else { X d = tokenbuf; X if (!len) X (void)strcpy(d,"ARGV"); X if (*d == '$') { X arg[1].arg_type = A_INDREAD; X arg[1].arg_ptr.arg_stab = stabent(d+1,TRUE); X } X else { X arg[1].arg_type = A_READ; X arg[1].arg_ptr.arg_stab = stabent(d,TRUE); X if (!stab_io(arg[1].arg_ptr.arg_stab)) X stab_io(arg[1].arg_ptr.arg_stab) = stio_new(); X if (strEQ(d,"ARGV")) { X (void)aadd(arg[1].arg_ptr.arg_stab); X stab_io(arg[1].arg_ptr.arg_stab)->flags |= X IOF_ARGV|IOF_START; X } X } X } X break; X X case 'q': X s++; X if (*s == 'q') { X s++; X goto do_double; X } X if (*s == 'x') { X s++; X goto do_back; X } X /* FALL THROUGH */ X case '\'': X do_single: X term = *s; X arg[1].arg_type = A_SINGLE; X leave = Nullch; X goto snarf_it; X X case '"': X do_double: X term = *s; X arg[1].arg_type = A_DOUBLE; X makesingle = TRUE; /* maybe disable runtime scanning */ X alwaysdollar = TRUE; /* treat $) and $| as variables */ X goto snarf_it; X case '`': X do_back: X term = *s; X arg[1].arg_type = A_BACKTICK; X set_csh(); X alwaysdollar = TRUE; /* treat $) and $| as variables */ X snarf_it: X { X STR *tmpstr; X char *tmps; X X multi_start = curcmd->c_line; X if (hereis) X multi_open = multi_close = '<'; X else { X multi_open = term; X if (term && (tmps = index("([{< )]}> )]}>",term))) X term = tmps[5]; X multi_close = term; X } X tmpstr = Str_new(87,80); X if (hereis) { X term = *tokenbuf; X if (!rsfp) { X d = s; X while (s < bufend && X (*s != term || bcmp(s,tokenbuf,len) != 0) ) { X if (*s++ == '\n') X curcmd->c_line++; X } X if (s >= bufend) { X curcmd->c_line = multi_start; X fatal("EOF in string"); X } X str_nset(tmpstr,d+1,s-d); X s += len - 1; X str_ncat(herewas,s,bufend-s); X str_replace(linestr,herewas); !STUFFY!FUNK! echo " " echo "End of kit 4 (of 36)" cat /dev/null >kit4isdone run='' config='' for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36; do if test -f kit${iskit}isdone; then run="$run $iskit" else todo="$todo $iskit" fi done case $todo in '') echo "You have run all your kits. Please read README and then type Configure." for combo in *:AA; do if test -f "$combo"; then realfile=`basename $combo :AA` cat $realfile:[A-Z][A-Z] >$realfile rm -rf $realfile:[A-Z][A-Z] fi done rm -rf kit*isdone chmod 755 Configure ;; *) echo "You have run$run." echo "You still need to run$todo." ;; esac : Someone might mail this, so... exit exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.