home *** CD-ROM | disk | FTP | other *** search
- /* $RCSfile: toke.c,v $$Revision: 4.0.1.8 $$Date: 92/06/23 12:33:45 $
- *
- * 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.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;
- }
-
- void
- check_uni() {
- char *s;
- char ch;
-
- if (oldoldbufptr != last_uni)
- return;
- while (isSPACE(*last_uni))
- last_uni++;
- for (s = last_uni; isALNUM(*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)
-
- int
- uni(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;
- }
-
- int
- lop(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 */
-
- int
- yylex()
- {
- 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++;
- 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 ')':
- case ']':
- tmp = *s++;
- TERM(tmp);
- case '}':
- *s |= 128;
- RETURN(';');
- case '&':
- s++;
- tmp = *s++;
- if (tmp == '&')
- OPERATOR(ANDAND);
- s--;
- if (expectterm) {
- d = bufend;
- while (s < d && isSPACE(*s))
- s++;
- if (isALPHA(*s) || *s == '_' || *s == '\'')
- *(--s) = '\\'; /* force next ident to WORD */
- else
- check_uni();
- OPERATOR(AMPER);
- }
- OPERATOR('&');
- case '|':
- s++;
- tmp = *s++;
- if (tmp == '|')
- OPERATOR(OROR);
- s--;
- OPERATOR('|');
- case '=':
- s++;
- tmp = *s++;
- if (tmp == '=')
- EOP(O_EQ);
- if (tmp == '~')
- OPERATOR(MATCH);
- s--;
- OPERATOR('=');
- case '!':
- s++;
- tmp = *s++;
- if (tmp == '=')
- EOP(O_NE);
- if (tmp == '~')
- OPERATOR(NMATCH);
- s--;
- OPERATOR('!');
- case '<':
- if (expectterm) {
- if (s[1] != '<' && !index(s,'>'))
- check_uni();
- s = scanstr(s, SCAN_DEF);
- TERM(RSTRING);
- }
- s++;
- tmp = *s++;
- if (tmp == '<')
- OPERATOR(LS);
- if (tmp == '=') {
- tmp = *s++;
- if (tmp == '>')
- EOP(O_NCMP);
- s--;
- ROP(O_LE);
- }
- s--;
- ROP(O_LT);
- case '>':
- s++;
- tmp = *s++;
- if (tmp == '>')
- OPERATOR(RS);
- if (tmp == '=')
- ROP(O_GE);
- s--;
- ROP(O_GT);
-
- #define SNARFWORD \
- d = tokenbuf; \
- while (isALNUM(*s) || *s == '\'') \
- *d++ = *s++; \
- while (d[-1] == '\'') \
- d--,s--; \
- *d = '\0'; \
- d = tokenbuf;
-
- case '$':
- if (s[1] == '#' && (isALPHA(s[2]) || s[2] == '_')) {
- s++;
- s = scanident(s,bufend,tokenbuf);
- yylval.stabval = aadd(stabent(tokenbuf,TRUE));
- TERM(ARYLEN);
- }
- d = s;
- s = scanident(s,bufend,tokenbuf);
- if (reparse) { /* turn ${foo[bar]} into ($foo[bar]) */
- do_reparse:
- s[-1] = ')';
- s = d;
- s[1] = s[0];
- s[0] = '(';
- goto retry;
- }
- yylval.stabval = stabent(tokenbuf,TRUE);
- expectterm = FALSE;
- if (isSPACE(*s) && oldoldbufptr && oldoldbufptr < bufptr) {
- s++;
- while (isSPACE(*oldoldbufptr))
- oldoldbufptr++;
- if (*oldoldbufptr == 'p' && strnEQ(oldoldbufptr,"print",5)) {
- if (index("&*<%", *s) && isALPHA(s[1]))
- expectterm = TRUE; /* e.g. print $fh &sub */
- else if (*s == '.' && isDIGIT(s[1]))
- expectterm = TRUE; /* e.g. print $fh .3 */
- else if (index("/?-+", *s) && !isSPACE(s[1]))
- expectterm = TRUE; /* e.g. print $fh -1 */
- }
- }
- RETURN(REG);
-
- case '@':
- d = s;
- s = scanident(s,bufend,tokenbuf);
- if (reparse)
- goto do_reparse;
- yylval.stabval = aadd(stabent(tokenbuf,TRUE));
- TERM(ARY);
-
- case '/': /* may either be division or pattern */
- case '?': /* may either be conditional or pattern */
- if (expectterm) {
- check_uni();
- s = scanpat(s);
- TERM(PATTERN);
- }
- tmp = *s++;
- if (tmp == '/')
- MOP(O_DIVIDE);
- OPERATOR(tmp);
-
- case '.':
- if (!expectterm || !isDIGIT(s[1])) {
- tmp = *s++;
- if (*s == tmp) {
- s++;
- if (*s == tmp) {
- s++;
- yylval.ival = 0;
- }
- else
- yylval.ival = AF_COMMON;
- OPERATOR(DOTDOT);
- }
- if (expectterm)
- check_uni();
- AOP(O_CONCAT);
- }
- /* FALL THROUGH */
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case '\'': case '"': case '`':
- s = scanstr(s, SCAN_DEF);
- TERM(RSTRING);
-
- case '\\': /* some magic to force next word to be a WORD */
- s++; /* used by do and sub to force a separate namespace */
- if (!isALPHA(*s) && *s != '_' && *s != '\'') {
- warn("Spurious backslash ignored");
- goto retry;
- }
- /* FALL THROUGH */
- case '_':
- SNARFWORD;
- if (d[1] == '_') {
- if (strEQ(d,"__LINE__") || strEQ(d,"__FILE__")) {
- ARG *arg = op_new(1);
-
- yylval.arg = arg;
- arg->arg_type = O_ITEM;
- if (d[2] == 'L')
- (void)sprintf(tokenbuf,"%ld",(long)curcmd->c_line);
- else
- strcpy(tokenbuf, stab_val(curcmd->c_filestab)->str_ptr);
- arg[1].arg_type = A_SINGLE;
- arg[1].arg_ptr.arg_str = str_make(tokenbuf,strlen(tokenbuf));
- TERM(RSTRING);
- }
- else if (strEQ(d,"__END__")) {
- STAB *stab;
- int fd;
-
- /*SUPPRESS 560*/
- if (!in_eval && (stab = stabent("DATA",FALSE))) {
- stab->str_pok |= SP_MULTI;
- if (!stab_io(stab))
- stab_io(stab) = stio_new();
- stab_io(stab)->ifp = rsfp;
- #if defined(HAS_FCNTL) && defined(F_SETFD)
- fd = fileno(rsfp);
- fcntl(fd,F_SETFD,fd >= 3);
- #endif
- if (preprocess)
- stab_io(stab)->type = '|';
- else if ((FILE*)rsfp == stdin)
- stab_io(stab)->type = '-';
- else
- stab_io(stab)->type = '<';
- rsfp = Nullfp;
- }
- goto fake_eof;
- }
- }
- break;
- case 'a': case 'A':
- SNARFWORD;
- if (strEQ(d,"alarm"))
- UNI(O_ALARM);
- if (strEQ(d,"accept"))
- FOP22(O_ACCEPT);
- if (strEQ(d,"atan2"))
- FUN2(O_ATAN2);
- break;
- case 'b': case 'B':
- SNARFWORD;
- if (strEQ(d,"bind"))
- FOP2(O_BIND);
- if (strEQ(d,"binmode"))
- FOP(O_BINMODE);
- break;
- case 'c': case 'C':
- SNARFWORD;
- if (strEQ(d,"chop"))
- LFUN(O_CHOP);
- if (strEQ(d,"continue"))
- OPERATOR(CONTINUE);
- if (strEQ(d,"chdir")) {
- (void)stabent("ENV",TRUE); /* may use HOME */
- UNI(O_CHDIR);
- }
- if (strEQ(d,"close"))
- FOP(O_CLOSE);
- if (strEQ(d,"closedir"))
- FOP(O_CLOSEDIR);
- if (strEQ(d,"cmp"))
- EOP(O_SCMP);
- if (strEQ(d,"caller"))
- UNI(O_CALLER);
- if (strEQ(d,"crypt")) {
- #ifdef FCRYPT
- static int cryptseen = 0;
-
- if (!cryptseen++)
- init_des();
- #endif
- FUN2(O_CRYPT);
- }
- if (strEQ(d,"chmod"))
- LOP(O_CHMOD);
- if (strEQ(d,"chown"))
- LOP(O_CHOWN);
- if (strEQ(d,"connect"))
- FOP2(O_CONNECT);
- if (strEQ(d,"cos"))
- UNI(O_COS);
- if (strEQ(d,"chroot"))
- UNI(O_CHROOT);
- break;
- case 'd': case 'D':
- SNARFWORD;
- if (strEQ(d,"do")) {
- d = bufend;
- while (s < d && isSPACE(*s))
- s++;
- if (isALPHA(*s) || *s == '_')
- *(--s) = '\\'; /* force next ident to WORD */
- OPERATOR(DO);
- }
- if (strEQ(d,"die"))
- LOP(O_DIE);
- if (strEQ(d,"defined"))
- LFUN(O_DEFINED);
- if (strEQ(d,"delete"))
- OPERATOR(DELETE);
- if (strEQ(d,"dbmopen"))
- HFUN3(O_DBMOPEN);
- if (strEQ(d,"dbmclose"))
- HFUN(O_DBMCLOSE);
- if (strEQ(d,"dump"))
- LOOPX(O_DUMP);
- break;
- case 'e': case 'E':
- SNARFWORD;
- if (strEQ(d,"else"))
- OPERATOR(ELSE);
- if (strEQ(d,"elsif")) {
- yylval.ival = curcmd->c_line;
- OPERATOR(ELSIF);
- }
- if (strEQ(d,"eq") || strEQ(d,"EQ"))
- EOP(O_SEQ);
- if (strEQ(d,"exit"))
- UNI(O_EXIT);
- if (strEQ(d,"eval")) {
- allstabs = TRUE; /* must initialize everything since */
- UNI(O_EVAL); /* we don't know what will be used */
- }
- if (strEQ(d,"eof"))
- FOP(O_EOF);
- if (strEQ(d,"exp"))
- UNI(O_EXP);
- if (strEQ(d,"each"))
- HFUN(O_EACH);
- if (strEQ(d,"exec")) {
- set_csh();
- LOP(O_EXEC_OP);
- }
- if (strEQ(d,"endhostent"))
- FUN0(O_EHOSTENT);
- if (strEQ(d,"endnetent"))
- FUN0(O_ENETENT);
- if (strEQ(d,"endservent"))
- FUN0(O_ESERVENT);
- if (strEQ(d,"endprotoent"))
- FUN0(O_EPROTOENT);
- if (strEQ(d,"endpwent"))
- FUN0(O_EPWENT);
- if (strEQ(d,"endgrent"))
- FUN0(O_EGRENT);
- break;
- case 'f': case 'F':
- SNARFWORD;
- if (strEQ(d,"for") || strEQ(d,"foreach")) {
- yylval.ival = curcmd->c_line;
- while (s < bufend && isSPACE(*s))
- s++;
- if (isALPHA(*s))
- fatal("Missing $ on loop variable");
- OPERATOR(FOR);
- }
- if (strEQ(d,"format")) {
- d = bufend;
- while (s < d && isSPACE(*s))
- s++;
- if (isALPHA(*s) || *s == '_')
- *(--s) = '\\'; /* force next ident to WORD */
- in_format = TRUE;
- allstabs = TRUE; /* must initialize everything since */
- OPERATOR(FORMAT); /* we don't know what will be used */
- }
- if (strEQ(d,"fork"))
- FUN0(O_FORK);
- if (strEQ(d,"fcntl"))
- FOP3(O_FCNTL);
- if (strEQ(d,"fileno"))
- FOP(O_FILENO);
- if (strEQ(d,"flock"))
- FOP2(O_FLOCK);
- break;
- case 'g': case 'G':
- SNARFWORD;
- if (strEQ(d,"gt") || strEQ(d,"GT"))
- ROP(O_SGT);
- if (strEQ(d,"ge") || strEQ(d,"GE"))
- ROP(O_SGE);
- if (strEQ(d,"grep"))
- FL2(O_GREP);
- if (strEQ(d,"goto"))
- LOOPX(O_GOTO);
- if (strEQ(d,"gmtime"))
- UNI(O_GMTIME);
- if (strEQ(d,"getc"))
- FOP(O_GETC);
- if (strnEQ(d,"get",3)) {
- d += 3;
- if (*d == 'p') {
- if (strEQ(d,"ppid"))
- FUN0(O_GETPPID);
- if (strEQ(d,"pgrp"))
- UNI(O_GETPGRP);
- if (strEQ(d,"priority"))
- FUN2(O_GETPRIORITY);
- if (strEQ(d,"protobyname"))
- UNI(O_GPBYNAME);
- if (strEQ(d,"protobynumber"))
- FUN1(O_GPBYNUMBER);
- if (strEQ(d,"protoent"))
- FUN0(O_GPROTOENT);
- if (strEQ(d,"pwent"))
- FUN0(O_GPWENT);
- if (strEQ(d,"pwnam"))
- FUN1(O_GPWNAM);
- if (strEQ(d,"pwuid"))
- FUN1(O_GPWUID);
- if (strEQ(d,"peername"))
- FOP(O_GETPEERNAME);
- }
- else if (*d == 'h') {
- if (strEQ(d,"hostbyname"))
- UNI(O_GHBYNAME);
- if (strEQ(d,"hostbyaddr"))
- FUN2(O_GHBYADDR);
- if (strEQ(d,"hostent"))
- FUN0(O_GHOSTENT);
- }
- else if (*d == 'n') {
- if (strEQ(d,"netbyname"))
- UNI(O_GNBYNAME);
- if (strEQ(d,"netbyaddr"))
- FUN2(O_GNBYADDR);
- if (strEQ(d,"netent"))
- FUN0(O_GNETENT);
- }
- else if (*d == 's') {
- if (strEQ(d,"servbyname"))
- FUN2(O_GSBYNAME);
- if (strEQ(d,"servbyport"))
- FUN2(O_GSBYPORT);
- if (strEQ(d,"servent"))
- FUN0(O_GSERVENT);
- if (strEQ(d,"sockname"))
- FOP(O_GETSOCKNAME);
- if (strEQ(d,"sockopt"))
- FOP3(O_GSOCKOPT);
- }
- else if (*d == 'g') {
- if (strEQ(d,"grent"))
- FUN0(O_GGRENT);
- if (strEQ(d,"grnam"))
- FUN1(O_GGRNAM);
- if (strEQ(d,"grgid"))
- FUN1(O_GGRGID);
- }
- else if (*d == 'l') {
- if (strEQ(d,"login"))
- FUN0(O_GETLOGIN);
- }
- d -= 3;
- }
- break;
- case 'h': case 'H':
- SNARFWORD;
- if (strEQ(d,"hex"))
- UNI(O_HEX);
- break;
- case 'i': case 'I':
- SNARFWORD;
- if (strEQ(d,"if")) {
- yylval.ival = curcmd->c_line;
- OPERATOR(IF);
- }
- if (strEQ(d,"index"))
- FUN2x(O_INDEX);
- if (strEQ(d,"int"))
- UNI(O_INT);
- if (strEQ(d,"ioctl"))
- FOP3(O_IOCTL);
- break;
- case 'j': case 'J':
- SNARFWORD;
- if (strEQ(d,"join"))
- FL2(O_JOIN);
- break;
- case 'k': case 'K':
- SNARFWORD;
- if (strEQ(d,"keys"))
- HFUN(O_KEYS);
- if (strEQ(d,"kill"))
- LOP(O_KILL);
- break;
- case 'l': case 'L':
- SNARFWORD;
- if (strEQ(d,"last"))
- LOOPX(O_LAST);
- if (strEQ(d,"local"))
- OPERATOR(LOCAL);
- if (strEQ(d,"length"))
- UNI(O_LENGTH);
- if (strEQ(d,"lt") || strEQ(d,"LT"))
- ROP(O_SLT);
- if (strEQ(d,"le") || strEQ(d,"LE"))
- ROP(O_SLE);
- if (strEQ(d,"localtime"))
- UNI(O_LOCALTIME);
- if (strEQ(d,"log"))
- UNI(O_LOG);
- if (strEQ(d,"link"))
- FUN2(O_LINK);
- if (strEQ(d,"listen"))
- FOP2(O_LISTEN);
- if (strEQ(d,"lstat"))
- FOP(O_LSTAT);
- break;
- case 'm': case 'M':
- if (s[1] == '\'') {
- d = "m";
- s++;
- }
- else {
- SNARFWORD;
- }
- if (strEQ(d,"m")) {
- s = scanpat(s-1);
- if (yylval.arg)
- TERM(PATTERN);
- else
- RETURN(1); /* force error */
- }
- switch (d[1]) {
- case 'k':
- if (strEQ(d,"mkdir"))
- FUN2(O_MKDIR);
- break;
- case 's':
- if (strEQ(d,"msgctl"))
- FUN3(O_MSGCTL);
- if (strEQ(d,"msgget"))
- FUN2(O_MSGGET);
- if (strEQ(d,"msgrcv"))
- FUN5(O_MSGRCV);
- if (strEQ(d,"msgsnd"))
- FUN3(O_MSGSND);
- break;
- }
- break;
- case 'n': case 'N':
- SNARFWORD;
- if (strEQ(d,"next"))
- LOOPX(O_NEXT);
- if (strEQ(d,"ne") || strEQ(d,"NE"))
- EOP(O_SNE);
- break;
- case 'o': case 'O':
- SNARFWORD;
- if (strEQ(d,"open"))
- OPERATOR(OPEN);
- if (strEQ(d,"ord"))
- UNI(O_ORD);
- if (strEQ(d,"oct"))
- UNI(O_OCT);
- if (strEQ(d,"opendir"))
- FOP2(O_OPEN_DIR);
- break;
- case 'p': case 'P':
- SNARFWORD;
- if (strEQ(d,"print")) {
- checkcomma(s,d,"filehandle");
- LOP(O_PRINT);
- }
- if (strEQ(d,"printf")) {
- checkcomma(s,d,"filehandle");
- LOP(O_PRTF);
- }
- if (strEQ(d,"push")) {
- yylval.ival = O_PUSH;
- OPERATOR(PUSH);
- }
- if (strEQ(d,"pop"))
- OPERATOR(POP);
- if (strEQ(d,"pack"))
- FL2(O_PACK);
- if (strEQ(d,"package"))
- OPERATOR(PACKAGE);
- if (strEQ(d,"pipe"))
- FOP22(O_PIPE_OP);
- break;
- case 'q': case 'Q':
- SNARFWORD;
- if (strEQ(d,"q")) {
- s = scanstr(s-1, SCAN_DEF);
- TERM(RSTRING);
- }
- if (strEQ(d,"qq")) {
- s = scanstr(s-2, SCAN_DEF);
- TERM(RSTRING);
- }
- if (strEQ(d,"qx")) {
- s = scanstr(s-2, SCAN_DEF);
- TERM(RSTRING);
- }
- break;
- case 'r': case 'R':
- SNARFWORD;
- if (strEQ(d,"return"))
- OLDLOP(O_RETURN);
- if (strEQ(d,"require")) {
- allstabs = TRUE; /* must initialize everything since */
- UNI(O_REQUIRE); /* we don't know what will be used */
- }
- if (strEQ(d,"reset"))
- UNI(O_RESET);
- if (strEQ(d,"redo"))
- LOOPX(O_REDO);
- if (strEQ(d,"rename"))
- FUN2(O_RENAME);
- if (strEQ(d,"rand"))
- UNI(O_RAND);
- if (strEQ(d,"rmdir"))
- UNI(O_RMDIR);
- if (strEQ(d,"rindex"))
- FUN2x(O_RINDEX);
- if (strEQ(d,"read"))
- FOP3(O_READ);
- if (strEQ(d,"readdir"))
- FOP(O_READDIR);
- if (strEQ(d,"rewinddir"))
- FOP(O_REWINDDIR);
- if (strEQ(d,"recv"))
- FOP4(O_RECV);
- if (strEQ(d,"reverse"))
- LOP(O_REVERSE);
- if (strEQ(d,"readlink"))
- UNI(O_READLINK);
- break;
- case 's': case 'S':
- if (s[1] == '\'') {
- d = "s";
- s++;
- }
- else {
- SNARFWORD;
- }
- if (strEQ(d,"s")) {
- s = scansubst(s);
- if (yylval.arg)
- TERM(SUBST);
- else
- RETURN(1); /* force error */
- }
- switch (d[1]) {
- case 'a':
- case 'b':
- break;
- case 'c':
- if (strEQ(d,"scalar"))
- UNI(O_SCALAR);
- break;
- case 'd':
- break;
- case 'e':
- if (strEQ(d,"select"))
- OPERATOR(SSELECT);
- if (strEQ(d,"seek"))
- FOP3(O_SEEK);
- if (strEQ(d,"semctl"))
- FUN4(O_SEMCTL);
- if (strEQ(d,"semget"))
- FUN3(O_SEMGET);
- if (strEQ(d,"semop"))
- FUN2(O_SEMOP);
- if (strEQ(d,"send"))
- FOP3(O_SEND);
- if (strEQ(d,"setpgrp"))
- FUN2(O_SETPGRP);
- if (strEQ(d,"setpriority"))
- FUN3(O_SETPRIORITY);
- if (strEQ(d,"sethostent"))
- FUN1(O_SHOSTENT);
- if (strEQ(d,"setnetent"))
- FUN1(O_SNETENT);
- if (strEQ(d,"setservent"))
- FUN1(O_SSERVENT);
- if (strEQ(d,"setprotoent"))
- FUN1(O_SPROTOENT);
- if (strEQ(d,"setpwent"))
- FUN0(O_SPWENT);
- if (strEQ(d,"setgrent"))
- FUN0(O_SGRENT);
- if (strEQ(d,"seekdir"))
- FOP2(O_SEEKDIR);
- if (strEQ(d,"setsockopt"))
- FOP4(O_SSOCKOPT);
- break;
- case 'f':
- case 'g':
- break;
- case 'h':
- if (strEQ(d,"shift"))
- TERM(SHIFT);
- if (strEQ(d,"shmctl"))
- FUN3(O_SHMCTL);
- if (strEQ(d,"shmget"))
- FUN3(O_SHMGET);
- if (strEQ(d,"shmread"))
- FUN4(O_SHMREAD);
- if (strEQ(d,"shmwrite"))
- FUN4(O_SHMWRITE);
- if (strEQ(d,"shutdown"))
- FOP2(O_SHUTDOWN);
- break;
- case 'i':
- if (strEQ(d,"sin"))
- UNI(O_SIN);
- break;
- case 'j':
- case 'k':
- break;
- case 'l':
- if (strEQ(d,"sleep"))
- UNI(O_SLEEP);
- break;
- case 'm':
- case 'n':
- break;
- case 'o':
- if (strEQ(d,"socket"))
- FOP4(O_SOCKET);
- if (strEQ(d,"socketpair"))
- FOP25(O_SOCKPAIR);
- if (strEQ(d,"sort")) {
- checkcomma(s,d,"subroutine name");
- d = bufend;
- while (s < d && isSPACE(*s)) s++;
- if (*s == ';' || *s == ')') /* probably a close */
- fatal("sort is now a reserved word");
- if (isALPHA(*s) || *s == '_') {
- /*SUPPRESS 530*/
- for (d = s; isALNUM(*d); d++) ;
- strncpy(tokenbuf,s,d-s);
- tokenbuf[d-s] = '\0';
- if (strNE(tokenbuf,"keys") &&
- strNE(tokenbuf,"values") &&
- strNE(tokenbuf,"split") &&
- strNE(tokenbuf,"grep") &&
- strNE(tokenbuf,"readdir") &&
- strNE(tokenbuf,"unpack") &&
- strNE(tokenbuf,"do") &&
- strNE(tokenbuf,"eval") &&
- (d >= bufend || isSPACE(*d)) )
- *(--s) = '\\'; /* force next ident to WORD */
- }
- LOP(O_SORT);
- }
- break;
- case 'p':
- if (strEQ(d,"split"))
- TERM(SPLIT);
- if (strEQ(d,"sprintf"))
- FL(O_SPRINTF);
- if (strEQ(d,"splice")) {
- yylval.ival = O_SPLICE;
- OPERATOR(PUSH);
- }
- break;
- case 'q':
- if (strEQ(d,"sqrt"))
- UNI(O_SQRT);
- break;
- case 'r':
- if (strEQ(d,"srand"))
- UNI(O_SRAND);
- break;
- case 's':
- break;
- case 't':
- if (strEQ(d,"stat"))
- FOP(O_STAT);
- if (strEQ(d,"study")) {
- sawstudy++;
- LFUN(O_STUDY);
- }
- break;
- case 'u':
- if (strEQ(d,"substr"))
- FUN2x(O_SUBSTR);
- if (strEQ(d,"sub")) {
- yylval.ival = savestack->ary_fill; /* restore stuff on reduce */
- savelong(&subline);
- saveitem(subname);
-
- subline = curcmd->c_line;
- d = bufend;
- while (s < d && isSPACE(*s))
- s++;
- if (isALPHA(*s) || *s == '_' || *s == '\'') {
- str_sset(subname,curstname);
- str_ncat(subname,"'",1);
- for (d = s+1; isALNUM(*d) || *d == '\''; d++)
- /*SUPPRESS 530*/
- ;
- if (d[-1] == '\'')
- d--;
- str_ncat(subname,s,d-s);
- *(--s) = '\\'; /* force next ident to WORD */
- }
- else
- str_set(subname,"?");
- OPERATOR(SUB);
- }
- break;
- case 'v':
- case 'w':
- case 'x':
- break;
- case 'y':
- if (strEQ(d,"system")) {
- set_csh();
- LOP(O_SYSTEM);
- }
- if (strEQ(d,"symlink"))
- FUN2(O_SYMLINK);
- if (strEQ(d,"syscall"))
- LOP(O_SYSCALL);
- if (strEQ(d,"sysread"))
- FOP3(O_SYSREAD);
- if (strEQ(d,"syswrite"))
- FOP3(O_SYSWRITE);
- break;
- case 'z':
- break;
- }
- break;
- case 't': case 'T':
- SNARFWORD;
- if (strEQ(d,"tr")) {
- s = scantrans(s);
- if (yylval.arg)
- TERM(TRANS);
- else
- RETURN(1); /* force error */
- }
- if (strEQ(d,"tell"))
- FOP(O_TELL);
- if (strEQ(d,"telldir"))
- FOP(O_TELLDIR);
- if (strEQ(d,"time"))
- FUN0(O_TIME);
- if (strEQ(d,"times"))
- FUN0(O_TMS);
- if (strEQ(d,"truncate"))
- FOP2(O_TRUNCATE);
- break;
- case 'u': case 'U':
- SNARFWORD;
- if (strEQ(d,"using"))
- OPERATOR(USING);
- if (strEQ(d,"until")) {
- yylval.ival = curcmd->c_line;
- OPERATOR(UNTIL);
- }
- if (strEQ(d,"unless")) {
- yylval.ival = curcmd->c_line;
- OPERATOR(UNLESS);
- }
- if (strEQ(d,"unlink"))
- LOP(O_UNLINK);
- if (strEQ(d,"undef"))
- LFUN(O_UNDEF);
- if (strEQ(d,"unpack"))
- FUN2(O_UNPACK);
- if (strEQ(d,"utime"))
- LOP(O_UTIME);
- if (strEQ(d,"umask"))
- UNI(O_UMASK);
- if (strEQ(d,"unshift")) {
- yylval.ival = O_UNSHIFT;
- OPERATOR(PUSH);
- }
- break;
- case 'v': case 'V':
- SNARFWORD;
- if (strEQ(d,"values"))
- HFUN(O_VALUES);
- if (strEQ(d,"vec")) {
- sawvec = TRUE;
- FUN3(O_VEC);
- }
- break;
- case 'w': case 'W':
- SNARFWORD;
- if (strEQ(d,"while")) {
- yylval.ival = curcmd->c_line;
- OPERATOR(WHILE);
- }
- if (strEQ(d,"warn"))
- LOP(O_WARN);
- if (strEQ(d,"wait"))
- FUN0(O_WAIT);
- if (strEQ(d,"waitpid"))
- FUN2(O_WAITPID);
- if (strEQ(d,"wantarray")) {
- yylval.arg = op_new(1);
- yylval.arg->arg_type = O_ITEM;
- yylval.arg[1].arg_type = A_WANTARRAY;
- TERM(RSTRING);
- }
- if (strEQ(d,"write"))
- FOP(O_WRITE);
- break;
- case 'x': case 'X':
- if (*s == 'x' && isDIGIT(s[1]) && !expectterm) {
- s++;
- MOP(O_REPEAT);
- }
- SNARFWORD;
- if (strEQ(d,"x")) {
- if (!expectterm)
- MOP(O_REPEAT);
- check_uni();
- }
- break;
- case 'y': case 'Y':
- if (s[1] == '\'') {
- d = "y";
- s++;
- }
- else {
- SNARFWORD;
- }
- if (strEQ(d,"y")) {
- s = scantrans(s);
- TERM(TRANS);
- }
- break;
- case 'z': case 'Z':
- SNARFWORD;
- break;
- }
- yylval.cval = savestr(d);
- if (expectterm == 2) { /* special case: start of statement */
- while (isSPACE(*s)) s++;
- if (*s == ':') {
- s++;
- CLINE;
- OPERATOR(LABEL);
- }
- TERM(WORD);
- }
- expectterm = FALSE;
- if (oldoldbufptr && oldoldbufptr < bufptr) {
- while (isSPACE(*oldoldbufptr))
- oldoldbufptr++;
- if (*oldoldbufptr == 'p' && strnEQ(oldoldbufptr,"print",5))
- expectterm = TRUE;
- else if (*oldoldbufptr == 's' && strnEQ(oldoldbufptr,"sort",4))
- expectterm = TRUE;
- }
- return (CLINE, bufptr = s, (int)WORD);
- }
-
- void
- checkcomma(s,name,what)
- register char *s;
- char *name;
- char *what;
- {
- char *w;
-
- if (dowarn && *s == ' ' && s[1] == '(') {
- w = index(s,')');
- if (w)
- for (w++; *w && isSPACE(*w); w++) ;
- if (!w || !*w || !index(";|}", *w)) /* an advisory hack only... */
- warn("%s (...) interpreted as function",name);
- }
- while (s < bufend && isSPACE(*s))
- s++;
- if (*s == '(')
- s++;
- while (s < bufend && isSPACE(*s))
- s++;
- if (isALPHA(*s) || *s == '_') {
- w = s++;
- while (isALNUM(*s))
- s++;
- while (s < bufend && isSPACE(*s))
- s++;
- if (*s == ',') {
- *s = '\0';
- w = instr(
- "tell eof times getlogin wait length shift umask getppid \
- cos exp int log rand sin sqrt ord wantarray",
- w);
- *s = ',';
- if (w)
- return;
- fatal("No comma allowed after %s", what);
- }
- }
- }
-
- char *
- scanident(s,send,dest)
- register char *s;
- register char *send;
- char *dest;
- {
- register char *d;
- int brackets = 0;
-
- reparse = Nullch;
- s++;
- d = dest;
- if (isDIGIT(*s)) {
- while (isDIGIT(*s))
- *d++ = *s++;
- }
- else {
- while (isALNUM(*s) || *s == '\'')
- *d++ = *s++;
- }
- while (d > dest+1 && d[-1] == '\'')
- d--,s--;
- *d = '\0';
- d = dest;
- if (!*d) {
- *d = *s++;
- if (*d == '{' /* } */ ) {
- d = dest;
- brackets++;
- while (s < send && brackets) {
- if (!reparse && (d == dest || (*s && isALNUM(*s) ))) {
- *d++ = *s++;
- continue;
- }
- else if (!reparse)
- reparse = s;
- switch (*s++) {
- /* { */
- case '}':
- brackets--;
- if (reparse && reparse == s - 1)
- reparse = Nullch;
- break;
- case '{': /* } */
- brackets++;
- break;
- }
- }
- *d = '\0';
- d = dest;
- }
- else
- d[1] = '\0';
- }
- if (*d == '^' && (isUPPER(*s) || index("[\\]^_?", *s))) {
- #ifdef DEBUGGING
- if (*s == 'D')
- debug |= 32768;
- #endif
- *d = *s++ ^ 64;
- }
- return s;
- }
-
- void
- scanconst(spat,string,len)
- SPAT *spat;
- char *string;
- int len;
- {
- register STR *tmpstr;
- register char *t;
- register char *d;
- register char *e;
- char *origstring = string;
- static char *vert = "|";
-
- if (ninstr(string, string+len, vert, vert+1))
- return;
- if (*string == '^')
- string++, len--;
- tmpstr = Str_new(86,len);
- str_nset(tmpstr,string,len);
- t = str_get(tmpstr);
- e = t + len;
- tmpstr->str_u.str_useful = 100;
- for (d=t; d < e; ) {
- switch (*d) {
- case '{':
- if (isDIGIT(d[1]))
- e = d;
- else
- goto defchar;
- break;
- case '.': case '[': case '$': case '(': case ')': case '|': case '+':
- case '^':
- e = d;
- break;
- case '\\':
- if (d[1] && index("wWbB0123456789sSdDlLuUExc",d[1])) {
- e = d;
- break;
- }
- Move(d+1,d,e-d,char);
- e--;
- switch(*d) {
- case 'n':
- *d = '\n';
- break;
- case 't':
- *d = '\t';
- break;
- case 'f':
- *d = '\f';
- break;
- case 'r':
- *d = '\r';
- break;
- case 'e':
- *d = '\033';
- break;
- case 'a':
- *d = '\007';
- break;
- }
- /* FALL THROUGH */
- default:
- defchar:
- if (d[1] == '*' || (d[1] == '{' && d[2] == '0') || d[1] == '?') {
- e = d;
- break;
- }
- d++;
- }
- }
- if (d == t) {
- str_free(tmpstr);
- return;
- }
- *d = '\0';
- tmpstr->str_cur = d - t;
- if (d == t+len)
- spat->spat_flags |= SPAT_ALL;
- if (*origstring != '^')
- spat->spat_flags |= SPAT_SCANFIRST;
- spat->spat_short = tmpstr;
- spat->spat_slen = d - t;
- }
-
- char *
- scanpat(s)
- register char *s;
- {
- register SPAT *spat;
- register char *d;
- register char *e;
- int len;
- SPAT savespat;
- STR *str = Str_new(93,0);
- char delim;
-
- Newz(801,spat,1,SPAT);
- spat->spat_next = curstash->tbl_spatroot; /* link into spat list */
- curstash->tbl_spatroot = spat;
-
- switch (*s++) {
- case 'm':
- s++;
- break;
- case '/':
- break;
- case '?':
- spat->spat_flags |= SPAT_ONCE;
- break;
- default:
- fatal("panic: scanpat");
- }
- s = str_append_till(str,s,bufend,s[-1],patleave);
- if (s >= bufend) {
- str_free(str);
- yyerror("Search pattern not terminated");
- yylval.arg = Nullarg;
- return s;
- }
- delim = *s++;
- while (*s == 'i' || *s == 'o' || *s == 'g') {
- if (*s == 'i') {
- s++;
- sawi = TRUE;
- spat->spat_flags |= SPAT_FOLD;
- }
- if (*s == 'o') {
- s++;
- spat->spat_flags |= SPAT_KEEP;
- }
- if (*s == 'g') {
- s++;
- spat->spat_flags |= SPAT_GLOBAL;
- }
- }
- len = str->str_cur;
- e = str->str_ptr + len;
- if (delim == '\'')
- d = e;
- else
- d = str->str_ptr;
- for (; d < e; d++) {
- if (*d == '\\')
- d++;
- else if ((*d == '$' && d[1] && d[1] != '|' && d[1] != ')') ||
- (*d == '@')) {
- register ARG *arg;
-
- spat->spat_runtime = arg = op_new(1);
- arg->arg_type = O_ITEM;
- arg[1].arg_type = A_DOUBLE;
- arg[1].arg_ptr.arg_str = str_smake(str);
- d = scanident(d,bufend,buf);
- (void)stabent(buf,TRUE); /* make sure it's created */
- for (; d < e; d++) {
- if (*d == '\\')
- d++;
- else if (*d == '$' && d[1] && d[1] != '|' && d[1] != ')') {
- d = scanident(d,bufend,buf);
- (void)stabent(buf,TRUE);
- }
- else if (*d == '@') {
- d = scanident(d,bufend,buf);
- if (strEQ(buf,"ARGV") || strEQ(buf,"ENV") ||
- strEQ(buf,"SIG") || strEQ(buf,"INC"))
- (void)stabent(buf,TRUE);
- }
- }
- goto got_pat; /* skip compiling for now */
- }
- }
- if (spat->spat_flags & SPAT_FOLD)
- StructCopy(spat, &savespat, SPAT);
- scanconst(spat,str->str_ptr,len);
- if ((spat->spat_flags & SPAT_ALL) && (spat->spat_flags & SPAT_SCANFIRST)) {
- fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD);
- spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len,
- spat->spat_flags & SPAT_FOLD);
- /* Note that this regexp can still be used if someone says
- * something like /a/ && s//b/; so we can't delete it.
- */
- }
- else {
- if (spat->spat_flags & SPAT_FOLD)
- StructCopy(&savespat, spat, SPAT);
- if (spat->spat_short)
- fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD);
- spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len,
- spat->spat_flags & SPAT_FOLD);
- hoistmust(spat);
- }
- got_pat:
- str_free(str);
- yylval.arg = make_match(O_MATCH,stab2arg(A_STAB,defstab),spat);
- return s;
- }
-
- char *
- scansubst(start)
- char *start;
- {
- register char *s = start;
- register SPAT *spat;
- register char *d;
- register char *e;
- int len;
- STR *str = Str_new(93,0);
- char term = *s;
-
- if (term && (d = index("([{< )]}> )]}>",term)))
- term = d[5];
-
- Newz(802,spat,1,SPAT);
- spat->spat_next = curstash->tbl_spatroot; /* link into spat list */
- curstash->tbl_spatroot = spat;
-
- s = str_append_till(str,s+1,bufend,term,patleave);
- if (s >= bufend) {
- str_free(str);
- yyerror("Substitution pattern not terminated");
- yylval.arg = Nullarg;
- return s;
- }
- len = str->str_cur;
- e = str->str_ptr + len;
- for (d = str->str_ptr; d < e; d++) {
- if (*d == '\\')
- d++;
- else if ((*d == '$' && d[1] && d[1] != '|' && /*(*/ d[1] != ')') ||
- *d == '@' ) {
- register ARG *arg;
-
- spat->spat_runtime = arg = op_new(1);
- arg->arg_type = O_ITEM;
- arg[1].arg_type = A_DOUBLE;
- arg[1].arg_ptr.arg_str = str_smake(str);
- d = scanident(d,e,buf);
- (void)stabent(buf,TRUE); /* make sure it's created */
- for (; *d; d++) {
- if (*d == '$' && d[1] && d[-1] != '\\' && d[1] != '|') {
- d = scanident(d,e,buf);
- (void)stabent(buf,TRUE);
- }
- else if (*d == '@' && d[-1] != '\\') {
- d = scanident(d,e,buf);
- if (strEQ(buf,"ARGV") || strEQ(buf,"ENV") ||
- strEQ(buf,"SIG") || strEQ(buf,"INC"))
- (void)stabent(buf,TRUE);
- }
- }
- goto get_repl; /* skip compiling for now */
- }
- }
- scanconst(spat,str->str_ptr,len);
- get_repl:
- if (term != *start)
- s++;
- s = scanstr(s, SCAN_REPL);
- if (s >= bufend) {
- str_free(str);
- yyerror("Substitution replacement not terminated");
- yylval.arg = Nullarg;
- return s;
- }
- spat->spat_repl = yylval.arg;
- if ((spat->spat_repl[1].arg_type & A_MASK) == A_SINGLE)
- spat->spat_flags |= SPAT_CONST;
- else if ((spat->spat_repl[1].arg_type & A_MASK) == A_DOUBLE) {
- STR *tmpstr;
- register char *t;
-
- spat->spat_flags |= SPAT_CONST;
- tmpstr = spat->spat_repl[1].arg_ptr.arg_str;
- e = tmpstr->str_ptr + tmpstr->str_cur;
- for (t = tmpstr->str_ptr; t < e; t++) {
- if (*t == '$' && t[1] && (index("`'&+0123456789",t[1]) ||
- (t[1] == '{' /*}*/ && isDIGIT(t[2])) ))
- spat->spat_flags &= ~SPAT_CONST;
- }
- }
- while (*s == 'g' || *s == 'i' || *s == 'e' || *s == 'o') {
- int es = 0;
-
- if (*s == 'e') {
- s++;
- es++;
- if ((spat->spat_repl[1].arg_type & A_MASK) == A_DOUBLE)
- spat->spat_repl[1].arg_type = A_SINGLE;
- spat->spat_repl = make_op(
- (!es && spat->spat_repl[1].arg_type == A_SINGLE
- ? O_EVALONCE
- : O_EVAL),
- 2,
- spat->spat_repl,
- Nullarg,
- Nullarg);
- spat->spat_flags &= ~SPAT_CONST;
- }
- if (*s == 'g') {
- s++;
- spat->spat_flags |= SPAT_GLOBAL;
- }
- if (*s == 'i') {
- s++;
- sawi = TRUE;
- spat->spat_flags |= SPAT_FOLD;
- if (!(spat->spat_flags & SPAT_SCANFIRST)) {
- str_free(spat->spat_short); /* anchored opt doesn't do */
- spat->spat_short = Nullstr; /* case insensitive match */
- spat->spat_slen = 0;
- }
- }
- if (*s == 'o') {
- s++;
- spat->spat_flags |= SPAT_KEEP;
- }
- }
- if (spat->spat_short && (spat->spat_flags & SPAT_SCANFIRST))
- fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD);
- if (!spat->spat_runtime) {
- spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len,
- spat->spat_flags & SPAT_FOLD);
- hoistmust(spat);
- }
- yylval.arg = make_match(O_SUBST,stab2arg(A_STAB,defstab),spat);
- str_free(str);
- return s;
- }
-
- void
- hoistmust(spat)
- register SPAT *spat;
- {
- if (!spat->spat_short && spat->spat_regexp->regstart &&
- (!spat->spat_regexp->regmust || spat->spat_regexp->reganch & ROPT_ANCH)
- ) {
- if (!(spat->spat_regexp->reganch & ROPT_ANCH))
- spat->spat_flags |= SPAT_SCANFIRST;
- else if (spat->spat_flags & SPAT_FOLD)
- return;
- spat->spat_short = str_smake(spat->spat_regexp->regstart);
- }
- else if (spat->spat_regexp->regmust) {/* is there a better short-circuit? */
- if (spat->spat_short &&
- str_eq(spat->spat_short,spat->spat_regexp->regmust))
- {
- if (spat->spat_flags & SPAT_SCANFIRST) {
- str_free(spat->spat_short);
- spat->spat_short = Nullstr;
- }
- else {
- str_free(spat->spat_regexp->regmust);
- spat->spat_regexp->regmust = Nullstr;
- return;
- }
- }
- if (!spat->spat_short || /* promote the better string */
- ((spat->spat_flags & SPAT_SCANFIRST) &&
- (spat->spat_short->str_cur < spat->spat_regexp->regmust->str_cur) )){
- str_free(spat->spat_short); /* ok if null */
- spat->spat_short = spat->spat_regexp->regmust;
- spat->spat_regexp->regmust = Nullstr;
- spat->spat_flags |= SPAT_SCANFIRST;
- }
- }
- }
-
- char *
- scantrans(start)
- char *start;
- {
- register char *s = start;
- ARG *arg =
- l(make_op(O_TRANS,2,stab2arg(A_STAB,defstab),Nullarg,Nullarg));
- STR *tstr;
- STR *rstr;
- register char *t;
- register char *r;
- register short *tbl;
- register int i;
- register int j;
- int tlen, rlen;
- int squash;
- int delete;
- int complement;
-
- New(803,tbl,256,short);
- arg[2].arg_type = A_NULL;
- arg[2].arg_ptr.arg_cval = (char*) tbl;
-
- s = scanstr(s, SCAN_TR);
- if (s >= bufend) {
- yyerror("Translation pattern not terminated");
- yylval.arg = Nullarg;
- return s;
- }
- tstr = yylval.arg[1].arg_ptr.arg_str;
- yylval.arg[1].arg_ptr.arg_str = Nullstr;
- arg_free(yylval.arg);
- t = tstr->str_ptr;
- tlen = tstr->str_cur;
-
- if (s[-1] == *start)
- s--;
-
- s = scanstr(s, SCAN_TR|SCAN_REPL);
- if (s >= bufend) {
- yyerror("Translation replacement not terminated");
- yylval.arg = Nullarg;
- return s;
- }
- rstr = yylval.arg[1].arg_ptr.arg_str;
- yylval.arg[1].arg_ptr.arg_str = Nullstr;
- arg_free(yylval.arg);
- r = rstr->str_ptr;
- rlen = rstr->str_cur;
-
- complement = delete = squash = 0;
- while (*s == 'c' || *s == 'd' || *s == 's') {
- if (*s == 'c')
- complement = 1;
- else if (*s == 'd')
- delete = 2;
- else
- squash = 1;
- s++;
- }
- arg[2].arg_len = delete|squash;
- yylval.arg = arg;
- if (complement) {
- Zero(tbl, 256, short);
- for (i = 0; i < tlen; i++)
- tbl[t[i] & 0377] = -1;
- for (i = 0, j = 0; i < 256; i++) {
- if (!tbl[i]) {
- if (j >= rlen) {
- if (delete)
- tbl[i] = -2;
- else if (rlen)
- tbl[i] = r[j-1] & 0377;
- else
- tbl[i] = i;
- }
- else
- tbl[i] = r[j++] & 0377;
- }
- }
- }
- else {
- if (!rlen && !delete) {
- r = t; rlen = tlen;
- }
- for (i = 0; i < 256; i++)
- tbl[i] = -1;
- for (i = 0, j = 0; i < tlen; i++,j++) {
- if (j >= rlen) {
- if (delete) {
- if (tbl[t[i] & 0377] == -1)
- tbl[t[i] & 0377] = -2;
- continue;
- }
- --j;
- }
- if (tbl[t[i] & 0377] == -1)
- tbl[t[i] & 0377] = r[j] & 0377;
- }
- }
- str_free(tstr);
- str_free(rstr);
- return s;
- }
-
- char *
- scanstr(start, in_what)
- char *start;
- int in_what;
- {
- register char *s = start;
- register char term;
- register char *d;
- register ARG *arg;
- register char *send;
- register bool makesingle = FALSE;
- register STAB *stab;
- bool alwaysdollar = FALSE;
- bool hereis = FALSE;
- STR *herewas;
- STR *str;
- /* which backslash sequences to keep */
- char *leave = (in_what & SCAN_TR)
- ? "\\$@nrtfbeacx0123456789-"
- : "\\$@nrtfbeacx0123456789[{]}lLuUE";
- int len;
-
- arg = op_new(1);
- yylval.arg = arg;
- arg->arg_type = O_ITEM;
-
- switch (*s) {
- default: /* a substitution replacement */
- arg[1].arg_type = A_DOUBLE;
- makesingle = TRUE; /* maybe disable runtime scanning */
- term = *s;
- if (term == '\'')
- leave = Nullch;
- goto snarf_it;
- case '0':
- {
- unsigned long i;
- int shift;
-
- arg[1].arg_type = A_SINGLE;
- if (s[1] == 'x') {
- shift = 4;
- s += 2;
- }
- else if (s[1] == '.')
- goto decimal;
- else
- shift = 3;
- i = 0;
- for (;;) {
- switch (*s) {
- default:
- goto out;
- case '_':
- s++;
- break;
- case '8': case '9':
- if (shift != 4)
- yyerror("Illegal octal digit");
- /* FALL THROUGH */
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7':
- i <<= shift;
- i += *s++ & 15;
- break;
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
- if (shift != 4)
- goto out;
- i <<= 4;
- i += (*s++ & 7) + 9;
- break;
- }
- }
- out:
- str = Str_new(92,0);
- str_numset(str,(double)i);
- if (str->str_ptr) {
- Safefree(str->str_ptr);
- str->str_ptr = Nullch;
- str->str_len = str->str_cur = 0;
- }
- arg[1].arg_ptr.arg_str = str;
- }
- break;
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9': case '.':
- decimal:
- arg[1].arg_type = A_SINGLE;
- d = tokenbuf;
- while (isDIGIT(*s) || *s == '_') {
- if (*s == '_')
- s++;
- else
- *d++ = *s++;
- }
- if (*s == '.' && s[1] != '.') {
- *d++ = *s++;
- while (isDIGIT(*s) || *s == '_') {
- if (*s == '_')
- s++;
- else
- *d++ = *s++;
- }
- }
- if (*s && index("eE",*s) && index("+-0123456789",s[1])) {
- *d++ = *s++;
- if (*s == '+' || *s == '-')
- *d++ = *s++;
- while (isDIGIT(*s))
- *d++ = *s++;
- }
- *d = '\0';
- str = Str_new(92,0);
- str_numset(str,atof(tokenbuf));
- if (str->str_ptr) {
- Safefree(str->str_ptr);
- str->str_ptr = Nullch;
- str->str_len = str->str_cur = 0;
- }
- arg[1].arg_ptr.arg_str = str;
- break;
- case '<':
- if (in_what & (SCAN_REPL|SCAN_TR))
- goto do_double;
- if (*++s == '<') {
- hereis = TRUE;
- d = tokenbuf;
- if (!rsfp)
- *d++ = '\n';
- if (*++s && index("`'\"",*s)) {
- term = *s++;
- s = cpytill(d,s,bufend,term,&len);
- if (s < bufend)
- s++;
- d += len;
- }
- else {
- if (*s == '\\')
- s++, term = '\'';
- else
- term = '"';
- while (isALNUM(*s))
- *d++ = *s++;
- } /* assuming tokenbuf won't clobber */
- *d++ = '\n';
- *d = '\0';
- len = d - tokenbuf;
- d = "\n";
- if (rsfp || !(d=ninstr(s,bufend,d,d+1)))
- herewas = str_make(s,bufend-s);
- else
- s--, herewas = str_make(s,d-s);
- s += herewas->str_cur;
- if (term == '\'')
- goto do_single;
- if (term == '`')
- goto do_back;
- goto do_double;
- }
- d = tokenbuf;
- s = cpytill(d,s,bufend,'>',&len);
- if (s < bufend)
- s++;
- else
- fatal("Unterminated <> operator");
-
- if (*d == '$') d++;
- while (*d && (isALNUM(*d) || *d == '\''))
- d++;
- if (d - tokenbuf != len) {
- s = start;
- term = *s;
- arg[1].arg_type = A_GLOB;
- set_csh();
- alwaysdollar = TRUE; /* treat $) and $| as variables */
- goto snarf_it;
- }
- else {
- d = tokenbuf;
- if (!len)
- (void)strcpy(d,"ARGV");
- if (*d == '$') {
- arg[1].arg_type = A_INDREAD;
- arg[1].arg_ptr.arg_stab = stabent(d+1,TRUE);
- }
- else {
- arg[1].arg_type = A_READ;
- arg[1].arg_ptr.arg_stab = stabent(d,TRUE);
- if (!stab_io(arg[1].arg_ptr.arg_stab))
- stab_io(arg[1].arg_ptr.arg_stab) = stio_new();
- if (strEQ(d,"ARGV")) {
- (void)aadd(arg[1].arg_ptr.arg_stab);
- stab_io(arg[1].arg_ptr.arg_stab)->flags |=
- IOF_ARGV|IOF_START;
- }
- }
- }
- break;
-
- case 'q':
- s++;
- if (*s == 'q') {
- s++;
- goto do_double;
- }
- if (*s == 'x') {
- s++;
- goto do_back;
- }
- /* FALL THROUGH */
- case '\'':
- do_single:
- term = *s;
- arg[1].arg_type = A_SINGLE;
- leave = Nullch;
- goto snarf_it;
-
- case '"':
- do_double:
- term = *s;
- arg[1].arg_type = A_DOUBLE;
- makesingle = TRUE; /* maybe disable runtime scanning */
- alwaysdollar = TRUE; /* treat $) and $| as variables */
- goto snarf_it;
- case '`':
- do_back:
- term = *s;
- arg[1].arg_type = A_BACKTICK;
- set_csh();
- alwaysdollar = TRUE; /* treat $) and $| as variables */
- snarf_it:
- {
- STR *tmpstr;
- STR *tmpstr2 = Nullstr;
- char *tmps;
- bool dorange = FALSE;
-
- CLINE;
- multi_start = curcmd->c_line;
- if (hereis)
- multi_open = multi_close = '<';
- else {
- multi_open = term;
- if (term && (tmps = index("([{< )]}> )]}>",term)))
- term = tmps[5];
- multi_close = term;
- }
- tmpstr = Str_new(87,80);
- if (hereis) {
- term = *tokenbuf;
- if (!rsfp) {
- d = s;
- while (s < bufend &&
- (*s != term || bcmp(s,tokenbuf,len) != 0) ) {
- if (*s++ == '\n')
- curcmd->c_line++;
- }
- if (s >= bufend) {
- curcmd->c_line = multi_start;
- fatal("EOF in string");
- }
- str_nset(tmpstr,d+1,s-d);
- s += len - 1;
- str_ncat(herewas,s,bufend-s);
- str_replace(linestr,herewas);
- oldoldbufptr = oldbufptr = bufptr = s = str_get(linestr);
- bufend = linestr->str_ptr + linestr->str_cur;
- hereis = FALSE;
- }
- else
- str_nset(tmpstr,"",0); /* avoid "uninitialized" warning */
- }
- else
- s = str_append_till(tmpstr,s+1,bufend,term,leave);
- while (s >= bufend) { /* multiple line string? */
- if (!rsfp ||
- !(oldoldbufptr = oldbufptr = s = str_gets(linestr, rsfp, 0))) {
- curcmd->c_line = multi_start;
- fatal("EOF in string");
- }
- curcmd->c_line++;
- if (perldb) {
- STR *str = Str_new(88,0);
-
- str_sset(str,linestr);
- astore(stab_xarray(curcmd->c_filestab),
- (int)curcmd->c_line,str);
- }
- bufend = linestr->str_ptr + linestr->str_cur;
- if (hereis) {
- if (*s == term && bcmp(s,tokenbuf,len) == 0) {
- s = bufend - 1;
- *s = ' ';
- str_scat(linestr,herewas);
- bufend = linestr->str_ptr + linestr->str_cur;
- }
- else {
- s = bufend;
- str_scat(tmpstr,linestr);
- }
- }
- else
- s = str_append_till(tmpstr,s,bufend,term,leave);
- }
- multi_end = curcmd->c_line;
- s++;
- if (tmpstr->str_cur + 5 < tmpstr->str_len) {
- tmpstr->str_len = tmpstr->str_cur + 1;
- Renew(tmpstr->str_ptr, tmpstr->str_len, char);
- }
- if (arg[1].arg_type == A_SINGLE) {
- arg[1].arg_ptr.arg_str = tmpstr;
- break;
- }
- tmps = s;
- s = tmpstr->str_ptr;
- send = s + tmpstr->str_cur;
- while (s < send) { /* see if we can make SINGLE */
- if (*s == '\\' && s[1] && isDIGIT(s[1]) && !isDIGIT(s[2]) &&
- !alwaysdollar && s[1] != '0')
- *s = '$'; /* grandfather \digit in subst */
- if ((*s == '$' || *s == '@') && s+1 < send &&
- (alwaysdollar || (s[1] != ')' && s[1] != '|'))) {
- makesingle = FALSE; /* force interpretation */
- }
- else if (*s == '\\' && s+1 < send) {
- if (index("lLuUE",s[1]))
- makesingle = FALSE;
- s++;
- }
- s++;
- }
- s = d = tmpstr->str_ptr; /* assuming shrinkage only */
- while (s < send || dorange) {
- if (in_what & SCAN_TR) {
- if (dorange) {
- int i;
- int max;
- if (!tmpstr2) { /* oops, have to grow */
- tmpstr2 = str_smake(tmpstr);
- s = tmpstr2->str_ptr + (s - tmpstr->str_ptr);
- send = tmpstr2->str_ptr + (send - tmpstr->str_ptr);
- }
- i = d - tmpstr->str_ptr;
- STR_GROW(tmpstr, tmpstr->str_len + 256);
- d = tmpstr->str_ptr + i;
- d -= 2;
- max = d[1] & 0377;
- for (i = (*d & 0377); i <= max; i++)
- *d++ = i;
- dorange = FALSE;
- continue;
- }
- else if (*s == '-' && s+1 < send && d != tmpstr->str_ptr) {
- dorange = TRUE;
- s++;
- }
- }
- else {
- if ((*s == '$' && s+1 < send &&
- (alwaysdollar || /*(*/(s[1] != ')' && s[1] != '|')) ) ||
- (*s == '@' && s+1 < send) ) {
- if (s[1] == '#' && (isALPHA(s[2]) || s[2] == '_'))
- *d++ = *s++;
- len = scanident(s,send,tokenbuf) - s;
- if (*s == '$' || strEQ(tokenbuf,"ARGV")
- || strEQ(tokenbuf,"ENV")
- || strEQ(tokenbuf,"SIG")
- || strEQ(tokenbuf,"INC") )
- (void)stabent(tokenbuf,TRUE); /* add symbol */
- while (len--)
- *d++ = *s++;
- continue;
- }
- }
- if (*s == '\\' && s+1 < send) {
- s++;
- switch (*s) {
- case '-':
- if (in_what & SCAN_TR) {
- *d++ = *s++;
- continue;
- }
- /* FALL THROUGH */
- default:
- if (!makesingle && (!leave || (*s && index(leave,*s))))
- *d++ = '\\';
- *d++ = *s++;
- continue;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- *d++ = scanoct(s, 3, &len);
- s += len;
- continue;
- case 'x':
- *d++ = scanhex(++s, 2, &len);
- s += len;
- continue;
- case 'c':
- s++;
- *d = *s++;
- if (isLOWER(*d))
- *d = toupper(*d);
- *d++ ^= 64;
- continue;
- case 'b':
- *d++ = '\b';
- break;
- case 'n':
- *d++ = '\n';
- break;
- case 'r':
- *d++ = '\r';
- break;
- case 'f':
- *d++ = '\f';
- break;
- case 't':
- *d++ = '\t';
- break;
- case 'e':
- *d++ = '\033';
- break;
- case 'a':
- *d++ = '\007';
- break;
- }
- s++;
- continue;
- }
- *d++ = *s++;
- }
- *d = '\0';
-
- if (arg[1].arg_type == A_DOUBLE && makesingle)
- arg[1].arg_type = A_SINGLE; /* now we can optimize on it */
-
- tmpstr->str_cur = d - tmpstr->str_ptr;
- if (arg[1].arg_type == A_GLOB) {
- arg[1].arg_ptr.arg_stab = stab = genstab();
- stab_io(stab) = stio_new();
- str_sset(stab_val(stab), tmpstr);
- }
- else
- arg[1].arg_ptr.arg_str = tmpstr;
- s = tmps;
- if (tmpstr2)
- str_free(tmpstr2);
- break;
- }
- }
- if (hereis)
- str_free(herewas);
- return s;
- }
-
- FCMD *
- load_format()
- {
- FCMD froot;
- FCMD *flinebeg;
- char *eol;
- register FCMD *fprev = &froot;
- register FCMD *fcmd;
- register char *s;
- register char *t;
- register STR *str;
- bool noblank;
- bool repeater;
-
- Zero(&froot, 1, FCMD);
- s = bufptr;
- while (s < bufend || (rsfp && (s = str_gets(linestr,rsfp, 0)) != Nullch)) {
- curcmd->c_line++;
- if (in_eval && !rsfp) {
- eol = index(s,'\n');
- if (!eol++)
- eol = bufend;
- }
- else
- eol = bufend = linestr->str_ptr + linestr->str_cur;
- if (perldb) {
- STR *tmpstr = Str_new(89,0);
-
- str_nset(tmpstr, s, eol-s);
- astore(stab_xarray(curcmd->c_filestab), (int)curcmd->c_line,tmpstr);
- }
- if (*s == '.') {
- /*SUPPRESS 530*/
- for (t = s+1; *t == ' ' || *t == '\t'; t++) ;
- if (*t == '\n') {
- bufptr = s;
- return froot.f_next;
- }
- }
- if (*s == '#') {
- s = eol;
- continue;
- }
- flinebeg = Nullfcmd;
- noblank = FALSE;
- repeater = FALSE;
- while (s < eol) {
- Newz(804,fcmd,1,FCMD);
- fprev->f_next = fcmd;
- fprev = fcmd;
- for (t=s; t < eol && *t != '@' && *t != '^'; t++) {
- if (*t == '~') {
- noblank = TRUE;
- *t = ' ';
- if (t[1] == '~') {
- repeater = TRUE;
- t[1] = ' ';
- }
- }
- }
- fcmd->f_pre = nsavestr(s, t-s);
- fcmd->f_presize = t-s;
- s = t;
- if (s >= eol) {
- if (noblank)
- fcmd->f_flags |= FC_NOBLANK;
- if (repeater)
- fcmd->f_flags |= FC_REPEAT;
- break;
- }
- if (!flinebeg)
- flinebeg = fcmd; /* start values here */
- if (*s++ == '^')
- fcmd->f_flags |= FC_CHOP; /* for doing text filling */
- switch (*s) {
- case '*':
- fcmd->f_type = F_LINES;
- *s = '\0';
- break;
- case '<':
- fcmd->f_type = F_LEFT;
- while (*s == '<')
- s++;
- break;
- case '>':
- fcmd->f_type = F_RIGHT;
- while (*s == '>')
- s++;
- break;
- case '|':
- fcmd->f_type = F_CENTER;
- while (*s == '|')
- s++;
- break;
- case '#':
- case '.':
- /* Catch the special case @... and handle it as a string
- field. */
- if (*s == '.' && s[1] == '.') {
- goto default_format;
- }
- fcmd->f_type = F_DECIMAL;
- {
- char *p;
-
- /* Read a format in the form @####.####, where either group
- of ### may be empty, or the final .### may be missing. */
- while (*s == '#')
- s++;
- if (*s == '.') {
- s++;
- p = s;
- while (*s == '#')
- s++;
- fcmd->f_decimals = s-p;
- fcmd->f_flags |= FC_DP;
- } else {
- fcmd->f_decimals = 0;
- }
- }
- break;
- default:
- default_format:
- fcmd->f_type = F_LEFT;
- break;
- }
- if (fcmd->f_flags & FC_CHOP && *s == '.') {
- fcmd->f_flags |= FC_MORE;
- while (*s == '.')
- s++;
- }
- fcmd->f_size = s-t;
- }
- if (flinebeg) {
- again:
- if (s >= bufend &&
- (!rsfp || (s = str_gets(linestr, rsfp, 0)) == Nullch) )
- goto badform;
- curcmd->c_line++;
- if (in_eval && !rsfp) {
- eol = index(s,'\n');
- if (!eol++)
- eol = bufend;
- }
- else
- eol = bufend = linestr->str_ptr + linestr->str_cur;
- if (perldb) {
- STR *tmpstr = Str_new(90,0);
-
- str_nset(tmpstr, s, eol-s);
- astore(stab_xarray(curcmd->c_filestab),
- (int)curcmd->c_line,tmpstr);
- }
- if (strnEQ(s,".\n",2)) {
- bufptr = s;
- yyerror("Missing values line");
- return froot.f_next;
- }
- if (*s == '#') {
- s = eol;
- goto again;
- }
- str = flinebeg->f_unparsed = Str_new(91,eol - s);
- str->str_u.str_hash = curstash;
- str_nset(str,"(",1);
- flinebeg->f_line = curcmd->c_line;
- eol[-1] = '\0';
- if (!flinebeg->f_next->f_type || index(s, ',')) {
- eol[-1] = '\n';
- str_ncat(str, s, eol - s - 1);
- str_ncat(str,",$$);",5);
- s = eol;
- }
- else {
- eol[-1] = '\n';
- while (s < eol && isSPACE(*s))
- s++;
- t = s;
- while (s < eol) {
- switch (*s) {
- case ' ': case '\t': case '\n': case ';':
- str_ncat(str, t, s - t);
- str_ncat(str, "," ,1);
- while (s < eol && (isSPACE(*s) || *s == ';'))
- s++;
- t = s;
- break;
- case '$':
- str_ncat(str, t, s - t);
- t = s;
- s = scanident(s,eol,tokenbuf);
- str_ncat(str, t, s - t);
- t = s;
- if (s < eol && *s && index("$'\"",*s))
- str_ncat(str, ",", 1);
- break;
- case '"': case '\'':
- str_ncat(str, t, s - t);
- t = s;
- s++;
- while (s < eol && (*s != *t || s[-1] == '\\'))
- s++;
- if (s < eol)
- s++;
- str_ncat(str, t, s - t);
- t = s;
- if (s < eol && *s && index("$'\"",*s))
- str_ncat(str, ",", 1);
- break;
- default:
- yyerror("Please use commas to separate fields");
- }
- }
- str_ncat(str,"$$);",4);
- }
- }
- }
- badform:
- bufptr = str_get(linestr);
- yyerror("Format not terminated");
- return froot.f_next;
- }
-
- static void
- set_csh()
- {
- #ifdef CSH
- if (!cshlen)
- cshlen = strlen(cshname);
- #endif
- }
-