1 /* $Header: toke.c,v 3.0.1.12 91/01/11 18:31:45 lwall Locked $
3 * Copyright (c) 1989, Larry Wall
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
9 * Revision 3.0.1.12 91/01/11 18:31:45 lwall
10 * patch42: eval'ed formats without proper termination blew up
11 * patch42: whitespace now allowed after terminating . of format
13 * Revision 3.0.1.11 90/11/10 02:13:44 lwall
14 * patch38: added alarm function
15 * patch38: tr was busted in metacharacters on signed char machines
17 * Revision 3.0.1.10 90/10/16 11:20:46 lwall
18 * patch29: the length of a search pattern was limited
19 * patch29: added DATA filehandle to read stuff after __END__
20 * patch29: added -M, -A and -C
21 * patch29: added cmp and <=>
22 * patch29: added caller
23 * patch29: added scalar
24 * patch29: added sysread and syswrite
25 * patch29: added SysV IPC
26 * patch29: added waitpid
27 * patch29: tr/// now understands c, d and s options, and handles nulls right
28 * patch29: 0x80000000 now makes unsigned value
29 * patch29: Null could not be used as a delimiter
30 * patch29: added @###.## fields to format
32 * Revision 3.0.1.9 90/08/13 22:37:25 lwall
33 * patch28: defined(@array) and defined(%array) didn't work right
35 * Revision 3.0.1.8 90/08/09 05:39:58 lwall
36 * patch19: added require operator
37 * patch19: added -x switch to extract script from input trash
38 * patch19: bare @name didn't add array to symbol table
39 * patch19: Added __LINE__ and __FILE__ tokens
40 * patch19: Added __END__ token
41 * patch19: Numeric literals are now stored only in floating point
42 * patch19: some support for FPS compiler misfunction
43 * patch19: "\\$foo" not handled right
44 * patch19: program and data can now both come from STDIN
45 * patch19: "here" strings caused warnings about uninitialized variables
47 * Revision 3.0.1.7 90/03/27 16:32:37 lwall
48 * patch16: MSDOS support
49 * patch16: formats didn't work inside eval
50 * patch16: final semicolon in program wasn't optional with -p or -n
52 * Revision 3.0.1.6 90/03/12 17:06:36 lwall
53 * patch13: last semicolon of program is now optional, just for Randal
54 * patch13: added splice operator: @oldelems = splice(@array,$offset,$len,LIST)
56 * Revision 3.0.1.5 90/02/28 18:47:06 lwall
57 * patch9: return grandfathered to never be function call
58 * patch9: non-existent perldb.pl now gives reasonable error message
59 * patch9: perl can now start up other interpreters scripts
60 * patch9: line numbers were bogus during certain portions of foreach evaluation
61 * patch9: null hereis core dumped
63 * Revision 3.0.1.4 89/12/21 20:26:56 lwall
64 * patch7: -d switch incompatible with -p or -n
65 * patch7: " ''$foo'' " didn't parse right
66 * patch7: grandfathered m'pat' and s'pat'repl' to not be package qualifiers
68 * Revision 3.0.1.3 89/11/17 15:43:15 lwall
69 * patch5: IBM PC/RT compiler can't deal with UNI() and LOP() macros
70 * patch5: } misadjusted expection of subsequent term or operator
71 * patch5: y/abcde// didn't work
73 * Revision 3.0.1.2 89/11/11 05:04:42 lwall
74 * patch2: fixed a CLINE macro conflict
76 * Revision 3.0.1.1 89/10/26 23:26:21 lwall
77 * patch1: disambiguated word after "sort" better
79 * Revision 3.0 89/10/18 15:32:33 lwall
92 /* which backslash sequences to keep in m// or s// */
94 static char *patleave = "\\.^$@dDwWsSbB+*?|()-nrtf0123456789[{]}";
96 char *reparse; /* if non-null, scanreg found ${foo[$bar]} */
101 #define CLINE (cmdline = (curcmd->c_line < cmdline ? curcmd->c_line : cmdline))
103 #define META(c) ((c) | 128)
105 #define RETURN(retval) return (bufptr = s,(int)retval)
106 #define OPERATOR(retval) return (expectterm = TRUE,bufptr = s,(int)retval)
107 #define TERM(retval) return (CLINE, expectterm = FALSE,bufptr = s,(int)retval)
108 #define LOOPX(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)LOOPEX)
109 #define FTST(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)FILETEST)
110 #define FUN0(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC0)
111 #define FUN1(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC1)
112 #define FUN2(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC2)
113 #define FUN2x(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC2x)
114 #define FUN3(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC3)
115 #define FUN4(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC4)
116 #define FUN5(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC5)
117 #define FL(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FLIST)
118 #define FL2(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FLIST2)
119 #define HFUN(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)HSHFUN)
120 #define HFUN3(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)HSHFUN3)
121 #define LFUN(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LVALFUN)
122 #define AOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)ADDOP)
123 #define MOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)MULOP)
124 #define EOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)EQOP)
125 #define ROP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)RELOP)
126 #define FOP(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP)
127 #define FOP2(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP2)
128 #define FOP3(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP3)
129 #define FOP4(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP4)
130 #define FOP22(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP22)
131 #define FOP25(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP25)
133 /* This bit of chicanery makes a unary function followed by
134 * a parenthesis into a function with one argument, highest precedence.
136 #define UNI(f) return(yylval.ival = f,expectterm = TRUE,bufptr = s, \
137 (*s == '(' || (s = skipspace(s), *s == '(') ? (int)FUNC1 : (int)UNIOP) )
139 /* This does similarly for list operators, merely by pretending that the
140 * paren came before the listop rather than after.
142 #define LOP(f) return(*s == '(' || (s = skipspace(s), *s == '(') ? \
143 (*s = META('('), bufptr = oldbufptr, '(') : \
144 (yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LISTOP))
145 /* grandfather return to old style */
146 #define OLDLOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LISTOP)
152 while (s < bufend && isascii(*s) && isspace(*s))
161 #define UNI(f) return uni(f,s)
162 #define LOP(f) return lop(f,s)
201 #endif /* CRIPPLED_CC */
205 register char *s = bufptr;
208 static bool in_format = FALSE;
209 static bool firstline = TRUE;
210 extern int yychar; /* last token */
212 oldoldbufptr = oldbufptr;
219 fprintf(stderr,"Tokener at %s",s);
221 fprintf(stderr,"Tokener at %s\n",s);
225 if ((*s & 127) == '(')
228 warn("Unrecognized character \\%03o ignored", *s++);
234 if ((*s & 127) == '(')
237 warn("Unrecognized character \\%03o ignored", *s++);
241 goto fake_eof; /* emulate EOF on ^D or ^Z */
246 goto retry; /* ignore stray nulls */
249 if (minus_n || minus_p || perldb) {
253 char *pdb = getenv("PERLDB");
255 str_cat(linestr, pdb ? pdb : "require 'perldb.pl'");
256 str_cat(linestr, ";");
258 if (minus_n || minus_p) {
259 str_cat(linestr,"line: while (<>) {");
261 str_cat(linestr,"@F=split(' ');");
263 oldoldbufptr = oldbufptr = s = str_get(linestr);
264 bufend = linestr->str_ptr + linestr->str_cur;
270 yylval.formval = load_format();
272 oldoldbufptr = oldbufptr = s = str_get(linestr) + 1;
273 bufend = linestr->str_ptr + linestr->str_cur;
279 #endif /* CRYPTSCRIPT */
281 if ((s = str_gets(linestr, rsfp, 0)) == Nullch) {
285 (void)mypclose(rsfp);
286 else if (rsfp == stdin)
292 if (minus_n || minus_p) {
293 str_set(linestr,minus_p ? ";}continue{print" : "");
294 str_cat(linestr,";}");
295 oldoldbufptr = oldbufptr = s = str_get(linestr);
296 bufend = linestr->str_ptr + linestr->str_cur;
297 minus_n = minus_p = 0;
300 oldoldbufptr = oldbufptr = s = str_get(linestr);
302 RETURN(';'); /* not infinite loop because rsfp is NULL now */
304 if (doextract && *linestr->str_ptr == '#')
307 oldoldbufptr = oldbufptr = bufptr = s;
309 STR *str = Str_new(85,0);
311 str_sset(str,linestr);
312 astore(stab_xarray(curcmd->c_filestab),(int)curcmd->c_line,str);
320 bufend = linestr->str_ptr + linestr->str_cur;
321 if (curcmd->c_line == 1) {
322 if (*s == '#' && s[1] == '!') {
323 if (!in_eval && !instr(s,"perl") && instr(origargv[0],"perl")) {
331 while (s < bufend && !isspace(*s))
334 while (s < bufend && isspace(*s))
337 Newz(899,newargv,origargc+3,char*);
339 while (s < bufend && !isspace(*s))
342 Copy(origargv+1, newargv+2, origargc+1, char*);
348 fatal("Can't exec %s", cmd);
352 while (s < bufend && isspace(*s))
354 if (*s == ':') /* for csh's that have to exec sh scripts */
359 case ' ': case '\t': case '\f':
363 if (preprocess && s == str_get(linestr) &&
364 s[1] == ' ' && isdigit(s[2])) {
365 curcmd->c_line = atoi(s+2)-1;
366 for (s += 2; isdigit(*s); s++) ;
368 while (s < d && isspace(*s)) s++;
369 s[strlen(s)-1] = '\0'; /* wipe out newline */
372 s[strlen(s)-1] = '\0'; /* wipe out trailing quote */
375 curcmd->c_filestab = fstab(s);
377 curcmd->c_filestab = fstab(origfilename);
378 oldoldbufptr = oldbufptr = s = str_get(linestr);
382 if (in_eval && !rsfp) {
384 while (s < d && *s != '\n')
389 STR *str = Str_new(85,0);
391 str_nset(str,linestr->str_ptr, s - linestr->str_ptr);
392 astore(stab_xarray(curcmd->c_filestab),(int)curcmd->c_line,str);
393 str_chop(linestr, s);
397 yylval.formval = load_format();
399 oldoldbufptr = oldbufptr = s = bufptr + 1;
410 if (s[1] && isalpha(s[1]) && !isalpha(s[2])) {
413 case 'r': FTST(O_FTEREAD);
414 case 'w': FTST(O_FTEWRITE);
415 case 'x': FTST(O_FTEEXEC);
416 case 'o': FTST(O_FTEOWNED);
417 case 'R': FTST(O_FTRREAD);
418 case 'W': FTST(O_FTRWRITE);
419 case 'X': FTST(O_FTREXEC);
420 case 'O': FTST(O_FTROWNED);
421 case 'e': FTST(O_FTIS);
422 case 'z': FTST(O_FTZERO);
423 case 's': FTST(O_FTSIZE);
424 case 'f': FTST(O_FTFILE);
425 case 'd': FTST(O_FTDIR);
426 case 'l': FTST(O_FTLINK);
427 case 'p': FTST(O_FTPIPE);
428 case 'S': FTST(O_FTSOCK);
429 case 'u': FTST(O_FTSUID);
430 case 'g': FTST(O_FTSGID);
431 case 'k': FTST(O_FTSVTX);
432 case 'b': FTST(O_FTBLK);
433 case 'c': FTST(O_FTCHR);
434 case 't': FTST(O_FTTTY);
435 case 'T': FTST(O_FTTEXT);
436 case 'B': FTST(O_FTBINARY);
437 case 'M': stabent("\024",TRUE); FTST(O_FTMTIME);
438 case 'A': stabent("\024",TRUE); FTST(O_FTATIME);
439 case 'C': stabent("\024",TRUE); FTST(O_FTCTIME);
467 s = scanreg(s,bufend,tokenbuf);
468 yylval.stabval = stabent(tokenbuf,TRUE);
479 s = scanreg(s,bufend,tokenbuf);
480 yylval.stabval = hadd(stabent(tokenbuf,TRUE));
496 if (isspace(*s) || *s == '#')
497 cmdline = NOLINE; /* invalidate current command line number */
500 if (curcmd->c_line < cmdline)
501 cmdline = curcmd->c_line;
519 while (s < d && isspace(*s))
521 if (isalpha(*s) || *s == '_' || *s == '\'')
522 *(--s) = '\\'; /* force next ident to WORD */
581 while (isascii(*s) && \
582 (isalpha(*s) || isdigit(*s) || *s == '_' || *s == '\'')) \
584 while (d[-1] == '\'') \
590 if (s[1] == '#' && (isalpha(s[2]) || s[2] == '_')) {
592 s = scanreg(s,bufend,tokenbuf);
593 yylval.stabval = aadd(stabent(tokenbuf,TRUE));
597 s = scanreg(s,bufend,tokenbuf);
598 if (reparse) { /* turn ${foo[bar]} into ($foo[bar]) */
606 yylval.stabval = stabent(tokenbuf,TRUE);
611 s = scanreg(s,bufend,tokenbuf);
614 yylval.stabval = aadd(stabent(tokenbuf,TRUE));
617 case '/': /* may either be division or pattern */
618 case '?': /* may either be conditional or pattern */
629 if (!expectterm || !isdigit(s[1])) {
638 case '0': case '1': case '2': case '3': case '4':
639 case '5': case '6': case '7': case '8': case '9':
640 case '\'': case '"': case '`':
644 case '\\': /* some magic to force next word to be a WORD */
645 s++; /* used by do and sub to force a separate namespace */
650 if (strEQ(d,"__LINE__") || strEQ(d,"__FILE__")) {
651 ARG *arg = op_new(1);
654 arg->arg_type = O_ITEM;
656 (void)sprintf(tokenbuf,"%ld",(long)curcmd->c_line);
658 strcpy(tokenbuf, stab_val(curcmd->c_filestab)->str_ptr);
659 arg[1].arg_type = A_SINGLE;
660 arg[1].arg_ptr.arg_str = str_make(tokenbuf,strlen(tokenbuf));
663 else if (strEQ(d,"__END__")) {
668 if (stab = stabent("DATA",FALSE)) {
669 stab->str_pok |= SP_MULTI;
670 stab_io(stab) = stio_new();
671 stab_io(stab)->ifp = rsfp;
672 #if defined(FCNTL) && defined(F_SETFD)
674 fcntl(fd,F_SETFD,fd >= 3);
677 stab_io(stab)->type = '|';
678 else if (rsfp == stdin)
679 stab_io(stab)->type = '-';
681 stab_io(stab)->type = '<';
691 if (strEQ(d,"alarm"))
693 if (strEQ(d,"accept"))
695 if (strEQ(d,"atan2"))
702 if (strEQ(d,"binmode"))
709 if (strEQ(d,"continue"))
711 if (strEQ(d,"chdir")) {
712 (void)stabent("ENV",TRUE); /* may use HOME */
715 if (strEQ(d,"close"))
717 if (strEQ(d,"closedir"))
721 if (strEQ(d,"caller"))
723 if (strEQ(d,"crypt")) {
729 if (strEQ(d,"chmod"))
731 if (strEQ(d,"chown"))
733 if (strEQ(d,"connect"))
737 if (strEQ(d,"chroot"))
744 while (s < d && isspace(*s))
746 if (isalpha(*s) || *s == '_')
747 *(--s) = '\\'; /* force next ident to WORD */
752 if (strEQ(d,"defined"))
754 if (strEQ(d,"delete"))
756 if (strEQ(d,"dbmopen"))
758 if (strEQ(d,"dbmclose"))
767 if (strEQ(d,"elsif")) {
768 yylval.ival = curcmd->c_line;
771 if (strEQ(d,"eq") || strEQ(d,"EQ"))
775 if (strEQ(d,"eval")) {
776 allstabs = TRUE; /* must initialize everything since */
777 UNI(O_EVAL); /* we don't know what will be used */
785 if (strEQ(d,"exec")) {
789 if (strEQ(d,"endhostent"))
791 if (strEQ(d,"endnetent"))
793 if (strEQ(d,"endservent"))
795 if (strEQ(d,"endprotoent"))
797 if (strEQ(d,"endpwent"))
799 if (strEQ(d,"endgrent"))
804 if (strEQ(d,"for") || strEQ(d,"foreach")) {
805 yylval.ival = curcmd->c_line;
808 if (strEQ(d,"format")) {
810 while (s < d && isspace(*s))
812 if (isalpha(*s) || *s == '_')
813 *(--s) = '\\'; /* force next ident to WORD */
815 allstabs = TRUE; /* must initialize everything since */
816 OPERATOR(FORMAT); /* we don't know what will be used */
820 if (strEQ(d,"fcntl"))
822 if (strEQ(d,"fileno"))
824 if (strEQ(d,"flock"))
829 if (strEQ(d,"gt") || strEQ(d,"GT"))
831 if (strEQ(d,"ge") || strEQ(d,"GE"))
837 if (strEQ(d,"gmtime"))
841 if (strnEQ(d,"get",3)) {
848 if (strEQ(d,"priority"))
850 if (strEQ(d,"protobyname"))
852 if (strEQ(d,"protobynumber"))
854 if (strEQ(d,"protoent"))
856 if (strEQ(d,"pwent"))
858 if (strEQ(d,"pwnam"))
860 if (strEQ(d,"pwuid"))
862 if (strEQ(d,"peername"))
865 else if (*d == 'h') {
866 if (strEQ(d,"hostbyname"))
868 if (strEQ(d,"hostbyaddr"))
870 if (strEQ(d,"hostent"))
873 else if (*d == 'n') {
874 if (strEQ(d,"netbyname"))
876 if (strEQ(d,"netbyaddr"))
878 if (strEQ(d,"netent"))
881 else if (*d == 's') {
882 if (strEQ(d,"servbyname"))
884 if (strEQ(d,"servbyport"))
886 if (strEQ(d,"servent"))
888 if (strEQ(d,"sockname"))
890 if (strEQ(d,"sockopt"))
893 else if (*d == 'g') {
894 if (strEQ(d,"grent"))
896 if (strEQ(d,"grnam"))
898 if (strEQ(d,"grgid"))
901 else if (*d == 'l') {
902 if (strEQ(d,"login"))
916 yylval.ival = curcmd->c_line;
919 if (strEQ(d,"index"))
923 if (strEQ(d,"ioctl"))
942 if (strEQ(d,"local"))
944 if (strEQ(d,"length"))
946 if (strEQ(d,"lt") || strEQ(d,"LT"))
948 if (strEQ(d,"le") || strEQ(d,"LE"))
950 if (strEQ(d,"localtime"))
956 if (strEQ(d,"listen"))
958 if (strEQ(d,"lstat"))
974 RETURN(1); /* force error */
978 if (strEQ(d,"mkdir"))
982 if (strEQ(d,"msgctl"))
984 if (strEQ(d,"msgget"))
986 if (strEQ(d,"msgrcv"))
988 if (strEQ(d,"msgsnd"))
997 if (strEQ(d,"ne") || strEQ(d,"NE"))
1002 if (strEQ(d,"open"))
1008 if (strEQ(d,"opendir"))
1013 if (strEQ(d,"print")) {
1014 checkcomma(s,"filehandle");
1017 if (strEQ(d,"printf")) {
1018 checkcomma(s,"filehandle");
1021 if (strEQ(d,"push")) {
1022 yylval.ival = O_PUSH;
1027 if (strEQ(d,"pack"))
1029 if (strEQ(d,"package"))
1031 if (strEQ(d,"pipe"))
1040 if (strEQ(d,"qq")) {
1047 if (strEQ(d,"return"))
1049 if (strEQ(d,"require")) {
1050 allstabs = TRUE; /* must initialize everything since */
1051 UNI(O_REQUIRE); /* we don't know what will be used */
1053 if (strEQ(d,"reset"))
1055 if (strEQ(d,"redo"))
1057 if (strEQ(d,"rename"))
1059 if (strEQ(d,"rand"))
1061 if (strEQ(d,"rmdir"))
1063 if (strEQ(d,"rindex"))
1065 if (strEQ(d,"read"))
1067 if (strEQ(d,"readdir"))
1069 if (strEQ(d,"rewinddir"))
1071 if (strEQ(d,"recv"))
1073 if (strEQ(d,"reverse"))
1075 if (strEQ(d,"readlink"))
1091 RETURN(1); /* force error */
1098 if (strEQ(d,"scalar"))
1104 if (strEQ(d,"select"))
1106 if (strEQ(d,"seek"))
1108 if (strEQ(d,"semctl"))
1110 if (strEQ(d,"semget"))
1112 if (strEQ(d,"semop"))
1114 if (strEQ(d,"send"))
1116 if (strEQ(d,"setpgrp"))
1118 if (strEQ(d,"setpriority"))
1119 FUN3(O_SETPRIORITY);
1120 if (strEQ(d,"sethostent"))
1122 if (strEQ(d,"setnetent"))
1124 if (strEQ(d,"setservent"))
1126 if (strEQ(d,"setprotoent"))
1128 if (strEQ(d,"setpwent"))
1130 if (strEQ(d,"setgrent"))
1132 if (strEQ(d,"seekdir"))
1134 if (strEQ(d,"setsockopt"))
1141 if (strEQ(d,"shift"))
1143 if (strEQ(d,"shmctl"))
1145 if (strEQ(d,"shmget"))
1147 if (strEQ(d,"shmread"))
1149 if (strEQ(d,"shmwrite"))
1151 if (strEQ(d,"shutdown"))
1162 if (strEQ(d,"sleep"))
1169 if (strEQ(d,"socket"))
1171 if (strEQ(d,"socketpair"))
1173 if (strEQ(d,"sort")) {
1174 checkcomma(s,"subroutine name");
1176 while (s < d && isascii(*s) && isspace(*s)) s++;
1177 if (*s == ';' || *s == ')') /* probably a close */
1178 fatal("sort is now a reserved word");
1179 if (isascii(*s) && (isalpha(*s) || *s == '_')) {
1180 for (d = s; isalpha(*d) || isdigit(*d) || *d == '_'; d++) ;
1181 strncpy(tokenbuf,s,d-s);
1182 if (strNE(tokenbuf,"keys") &&
1183 strNE(tokenbuf,"values") &&
1184 strNE(tokenbuf,"split") &&
1185 strNE(tokenbuf,"grep") &&
1186 strNE(tokenbuf,"readdir") &&
1187 strNE(tokenbuf,"unpack") &&
1188 strNE(tokenbuf,"do") &&
1189 (d >= bufend || isspace(*d)) )
1190 *(--s) = '\\'; /* force next ident to WORD */
1196 if (strEQ(d,"split"))
1198 if (strEQ(d,"sprintf"))
1200 if (strEQ(d,"splice")) {
1201 yylval.ival = O_SPLICE;
1206 if (strEQ(d,"sqrt"))
1210 if (strEQ(d,"srand"))
1216 if (strEQ(d,"stat"))
1218 if (strEQ(d,"study")) {
1224 if (strEQ(d,"substr"))
1226 if (strEQ(d,"sub")) {
1227 subline = curcmd->c_line;
1229 while (s < d && isspace(*s))
1231 if (isalpha(*s) || *s == '_' || *s == '\'') {
1233 str_sset(subname,curstname);
1234 str_ncat(subname,"'",1);
1236 isalpha(*d) || isdigit(*d) || *d == '_' || *d == '\'';
1240 str_ncat(subname,s,d-s);
1242 *(--s) = '\\'; /* force next ident to WORD */
1245 str_set(subname,"?");
1254 if (strEQ(d,"system")) {
1258 if (strEQ(d,"symlink"))
1260 if (strEQ(d,"syscall"))
1262 if (strEQ(d,"sysread"))
1264 if (strEQ(d,"syswrite"))
1273 if (strEQ(d,"tr")) {
1278 RETURN(1); /* force error */
1280 if (strEQ(d,"tell"))
1282 if (strEQ(d,"telldir"))
1284 if (strEQ(d,"time"))
1286 if (strEQ(d,"times"))
1288 if (strEQ(d,"truncate"))
1293 if (strEQ(d,"using"))
1295 if (strEQ(d,"until")) {
1296 yylval.ival = curcmd->c_line;
1299 if (strEQ(d,"unless")) {
1300 yylval.ival = curcmd->c_line;
1303 if (strEQ(d,"unlink"))
1305 if (strEQ(d,"undef"))
1307 if (strEQ(d,"unpack"))
1309 if (strEQ(d,"utime"))
1311 if (strEQ(d,"umask"))
1313 if (strEQ(d,"unshift")) {
1314 yylval.ival = O_UNSHIFT;
1320 if (strEQ(d,"values"))
1322 if (strEQ(d,"vec")) {
1329 if (strEQ(d,"while")) {
1330 yylval.ival = curcmd->c_line;
1333 if (strEQ(d,"warn"))
1335 if (strEQ(d,"wait"))
1337 if (strEQ(d,"waitpid"))
1339 if (strEQ(d,"wantarray")) {
1340 yylval.arg = op_new(1);
1341 yylval.arg->arg_type = O_ITEM;
1342 yylval.arg[1].arg_type = A_WANTARRAY;
1345 if (strEQ(d,"write"))
1350 if (!expectterm && strEQ(d,"x"))
1370 yylval.cval = savestr(d);
1372 if (oldoldbufptr && oldoldbufptr < bufptr) {
1373 while (isspace(*oldoldbufptr))
1375 if (*oldoldbufptr == 'p' && strnEQ(oldoldbufptr,"print",5))
1377 else if (*oldoldbufptr == 's' && strnEQ(oldoldbufptr,"sort",4))
1380 return (CLINE, bufptr = s, (int)WORD);
1392 while (s < bufend && isascii(*s) && isspace(*s))
1394 if (isascii(*s) && (isalpha(*s) || *s == '_')) {
1396 while (isalpha(*s) || isdigit(*s) || *s == '_')
1398 while (s < bufend && isspace(*s))
1403 "tell eof times getlogin wait length shift umask getppid \
1404 cos exp int log rand sin sqrt ord wantarray",
1409 fatal("No comma allowed after %s", what);
1415 scanreg(s,send,dest)
1417 register char *send;
1431 while (isalpha(*s) || isdigit(*s) || *s == '_' || *s == '\'')
1434 while (d > dest+1 && d[-1] == '\'')
1440 if (*d == '{' /* } */ ) {
1443 while (s < send && brackets) {
1444 if (!reparse && (d == dest || (*s && isascii(*s) &&
1445 (isalpha(*s) || isdigit(*s) || *s == '_') ))) {
1455 if (reparse && reparse == s - 1)
1469 if (*d == '^' && !isspace(*s))
1475 scanconst(string,len)
1479 register STR *retstr;
1484 if (index(string,'|')) {
1487 retstr = Str_new(86,len);
1488 str_nset(retstr,string,len);
1489 t = str_get(retstr);
1491 retstr->str_u.str_useful = 100;
1492 for (d=t; d < e; ) {
1500 case '.': case '[': case '$': case '(': case ')': case '|': case '+':
1504 if (d[1] && index("wWbB0123456789sSdD",d[1])) {
1508 (void)bcopy(d+1,d,e-d);
1527 if (d[1] == '*' || (d[1] == '{' && d[2] == '0') || d[1] == '?') {
1539 retstr->str_cur = d - t;
1547 register SPAT *spat;
1552 STR *str = Str_new(93,0);
1554 Newz(801,spat,1,SPAT);
1555 spat->spat_next = curstash->tbl_spatroot; /* link into spat list */
1556 curstash->tbl_spatroot = spat;
1565 spat->spat_flags |= SPAT_ONCE;
1568 fatal("panic: scanpat");
1570 s = str_append_till(str,s,bufend,s[-1],patleave);
1573 yyerror("Search pattern not terminated");
1574 yylval.arg = Nullarg;
1578 while (*s == 'i' || *s == 'o') {
1582 spat->spat_flags |= SPAT_FOLD;
1586 spat->spat_flags |= SPAT_KEEP;
1590 e = str->str_ptr + len;
1591 for (d = str->str_ptr; d < e; d++) {
1594 else if ((*d == '$' && d[1] && d[1] != '|' && d[1] != ')') ||
1598 spat->spat_runtime = arg = op_new(1);
1599 arg->arg_type = O_ITEM;
1600 arg[1].arg_type = A_DOUBLE;
1601 arg[1].arg_ptr.arg_str = str_smake(str);
1602 d = scanreg(d,bufend,buf);
1603 (void)stabent(buf,TRUE); /* make sure it's created */
1604 for (; d < e; d++) {
1607 else if (*d == '$' && d[1] && d[1] != '|' && d[1] != ')') {
1608 d = scanreg(d,bufend,buf);
1609 (void)stabent(buf,TRUE);
1611 else if (*d == '@') {
1612 d = scanreg(d,bufend,buf);
1613 if (strEQ(buf,"ARGV") || strEQ(buf,"ENV") ||
1614 strEQ(buf,"SIG") || strEQ(buf,"INC"))
1615 (void)stabent(buf,TRUE);
1618 goto got_pat; /* skip compiling for now */
1621 if (spat->spat_flags & SPAT_FOLD)
1625 (void)bcopy((char *)spat, (char *)&savespat, sizeof(SPAT));
1627 if (*str->str_ptr == '^') {
1628 spat->spat_short = scanconst(str->str_ptr+1,len-1);
1629 if (spat->spat_short) {
1630 spat->spat_slen = spat->spat_short->str_cur;
1631 if (spat->spat_slen == len - 1)
1632 spat->spat_flags |= SPAT_ALL;
1636 spat->spat_flags |= SPAT_SCANFIRST;
1637 spat->spat_short = scanconst(str->str_ptr,len);
1638 if (spat->spat_short) {
1639 spat->spat_slen = spat->spat_short->str_cur;
1640 if (spat->spat_slen == len)
1641 spat->spat_flags |= SPAT_ALL;
1644 if ((spat->spat_flags & SPAT_ALL) && (spat->spat_flags & SPAT_SCANFIRST)) {
1645 fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD);
1646 spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len,
1647 spat->spat_flags & SPAT_FOLD);
1648 /* Note that this regexp can still be used if someone says
1649 * something like /a/ && s//b/; so we can't delete it.
1653 if (spat->spat_flags & SPAT_FOLD)
1657 (void)bcopy((char *)&savespat, (char *)spat, sizeof(SPAT));
1659 if (spat->spat_short)
1660 fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD);
1661 spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len,
1662 spat->spat_flags & SPAT_FOLD,1);
1667 yylval.arg = make_match(O_MATCH,stab2arg(A_STAB,defstab),spat);
1675 register SPAT *spat;
1679 STR *str = Str_new(93,0);
1681 Newz(802,spat,1,SPAT);
1682 spat->spat_next = curstash->tbl_spatroot; /* link into spat list */
1683 curstash->tbl_spatroot = spat;
1685 s = str_append_till(str,s+1,bufend,*s,patleave);
1688 yyerror("Substitution pattern not terminated");
1689 yylval.arg = Nullarg;
1693 e = str->str_ptr + len;
1694 for (d = str->str_ptr; d < e; d++) {
1697 else if ((*d == '$' && d[1] && d[1] != '|' && /*(*/ d[1] != ')') ||
1701 spat->spat_runtime = arg = op_new(1);
1702 arg->arg_type = O_ITEM;
1703 arg[1].arg_type = A_DOUBLE;
1704 arg[1].arg_ptr.arg_str = str_smake(str);
1705 d = scanreg(d,bufend,buf);
1706 (void)stabent(buf,TRUE); /* make sure it's created */
1708 if (*d == '$' && d[1] && d[-1] != '\\' && d[1] != '|') {
1709 d = scanreg(d,bufend,buf);
1710 (void)stabent(buf,TRUE);
1712 else if (*d == '@' && d[-1] != '\\') {
1713 d = scanreg(d,bufend,buf);
1714 if (strEQ(buf,"ARGV") || strEQ(buf,"ENV") ||
1715 strEQ(buf,"SIG") || strEQ(buf,"INC"))
1716 (void)stabent(buf,TRUE);
1719 goto get_repl; /* skip compiling for now */
1722 if (*str->str_ptr == '^') {
1723 spat->spat_short = scanconst(str->str_ptr+1,len-1);
1724 if (spat->spat_short)
1725 spat->spat_slen = spat->spat_short->str_cur;
1728 spat->spat_flags |= SPAT_SCANFIRST;
1729 spat->spat_short = scanconst(str->str_ptr,len);
1730 if (spat->spat_short)
1731 spat->spat_slen = spat->spat_short->str_cur;
1737 yyerror("Substitution replacement not terminated");
1738 yylval.arg = Nullarg;
1741 spat->spat_repl = yylval.arg;
1742 spat->spat_flags |= SPAT_ONCE;
1743 if ((spat->spat_repl[1].arg_type & A_MASK) == A_SINGLE)
1744 spat->spat_flags |= SPAT_CONST;
1745 else if ((spat->spat_repl[1].arg_type & A_MASK) == A_DOUBLE) {
1749 spat->spat_flags |= SPAT_CONST;
1750 tmpstr = spat->spat_repl[1].arg_ptr.arg_str;
1751 e = tmpstr->str_ptr + tmpstr->str_cur;
1752 for (t = tmpstr->str_ptr; t < e; t++) {
1753 if (*t == '$' && t[1] && (index("`'&+0123456789",t[1]) ||
1754 (t[1] == '{' /*}*/ && isdigit(t[2])) ))
1755 spat->spat_flags &= ~SPAT_CONST;
1758 while (*s == 'g' || *s == 'i' || *s == 'e' || *s == 'o') {
1761 if ((spat->spat_repl[1].arg_type & A_MASK) == A_DOUBLE)
1762 spat->spat_repl[1].arg_type = A_SINGLE;
1763 spat->spat_repl = make_op(O_EVAL,2,
1767 spat->spat_flags &= ~SPAT_CONST;
1771 spat->spat_flags &= ~SPAT_ONCE;
1776 spat->spat_flags |= SPAT_FOLD;
1777 if (!(spat->spat_flags & SPAT_SCANFIRST)) {
1778 str_free(spat->spat_short); /* anchored opt doesn't do */
1779 spat->spat_short = Nullstr; /* case insensitive match */
1780 spat->spat_slen = 0;
1785 spat->spat_flags |= SPAT_KEEP;
1788 if (spat->spat_short && (spat->spat_flags & SPAT_SCANFIRST))
1789 fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD);
1790 if (!spat->spat_runtime) {
1791 spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len,
1792 spat->spat_flags & SPAT_FOLD,1);
1795 yylval.arg = make_match(O_SUBST,stab2arg(A_STAB,defstab),spat);
1801 register SPAT *spat;
1803 if (spat->spat_regexp->regmust) { /* is there a better short-circuit? */
1804 if (spat->spat_short &&
1805 str_eq(spat->spat_short,spat->spat_regexp->regmust))
1807 if (spat->spat_flags & SPAT_SCANFIRST) {
1808 str_free(spat->spat_short);
1809 spat->spat_short = Nullstr;
1812 str_free(spat->spat_regexp->regmust);
1813 spat->spat_regexp->regmust = Nullstr;
1817 if (!spat->spat_short || /* promote the better string */
1818 ((spat->spat_flags & SPAT_SCANFIRST) &&
1819 (spat->spat_short->str_cur < spat->spat_regexp->regmust->str_cur) )){
1820 str_free(spat->spat_short); /* ok if null */
1821 spat->spat_short = spat->spat_regexp->regmust;
1822 spat->spat_regexp->regmust = Nullstr;
1823 spat->spat_flags |= SPAT_SCANFIRST;
1829 expand_charset(s,len,retlen)
1835 register char *d = t;
1837 register char *send = s + len;
1839 while (s < send && d - t <= 256) {
1840 if (s[1] == '-' && s+2 < send) {
1841 for (i = s[0]; i <= s[2]; i++)
1850 return nsavestr(t,d-t);
1858 l(make_op(O_TRANS,2,stab2arg(A_STAB,defstab),Nullarg,Nullarg));
1861 register short *tbl;
1869 New(803,tbl,256,short);
1870 arg[2].arg_type = A_NULL;
1871 arg[2].arg_ptr.arg_cval = (char*) tbl;
1874 yyerror("Translation pattern not terminated");
1875 yylval.arg = Nullarg;
1878 t = expand_charset(yylval.arg[1].arg_ptr.arg_str->str_ptr,
1879 yylval.arg[1].arg_ptr.arg_str->str_cur,&tlen);
1880 free_arg(yylval.arg);
1883 yyerror("Translation replacement not terminated");
1884 yylval.arg = Nullarg;
1887 complement = delete = squash = 0;
1888 while (*s == 'c' || *s == 'd' || *s == 's') {
1897 r = expand_charset(yylval.arg[1].arg_ptr.arg_str->str_ptr,
1898 yylval.arg[1].arg_ptr.arg_str->str_cur,&rlen);
1899 free_arg(yylval.arg);
1900 arg[2].arg_len = delete|squash;
1902 if (!rlen && !delete) {
1907 Zero(tbl, 256, short);
1908 for (i = 0; i < tlen; i++)
1909 tbl[t[i] & 0377] = -1;
1910 for (i = 0, j = 0; i < 256; i++,j++) {
1924 for (i = 0; i < 256; i++)
1926 for (i = 0, j = 0; i < tlen; i++,j++) {
1929 if (tbl[t[i] & 0377] == -1)
1930 tbl[t[i] & 0377] = -2;
1935 if (tbl[t[i] & 0377] == -1)
1936 tbl[t[i] & 0377] = r[j] & 0377;
1952 register char *send;
1953 register bool makesingle = FALSE;
1954 register STAB *stab;
1955 bool alwaysdollar = FALSE;
1956 bool hereis = FALSE;
1959 char *leave = "\\$@nrtfb0123456789[{]}"; /* which backslash sequences to keep */
1964 arg->arg_type = O_ITEM;
1967 default: /* a substitution replacement */
1968 arg[1].arg_type = A_DOUBLE;
1969 makesingle = TRUE; /* maybe disable runtime scanning */
1979 arg[1].arg_type = A_SINGLE;
1984 else if (s[1] == '.')
1995 yyerror("Illegal octal digit");
1997 case '0': case '1': case '2': case '3': case '4':
1998 case '5': case '6': case '7':
2002 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
2003 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
2007 i += (*s++ & 7) + 9;
2012 str = Str_new(92,0);
2013 str_numset(str,(double)i);
2015 Safefree(str->str_ptr);
2016 str->str_ptr = Nullch;
2017 str->str_len = str->str_cur = 0;
2019 arg[1].arg_ptr.arg_str = str;
2022 case '1': case '2': case '3': case '4': case '5':
2023 case '6': case '7': case '8': case '9': case '.':
2025 arg[1].arg_type = A_SINGLE;
2027 while (isdigit(*s) || *s == '_') {
2033 if (*s == '.' && s[1] && index("0123456789eE ;",s[1])) {
2035 while (isdigit(*s) || *s == '_') {
2042 if (*s && index("eE",*s) && index("+-0123456789",s[1])) {
2044 if (*s == '+' || *s == '-')
2050 str = Str_new(92,0);
2051 str_numset(str,atof(tokenbuf));
2053 Safefree(str->str_ptr);
2054 str->str_ptr = Nullch;
2055 str->str_len = str->str_cur = 0;
2057 arg[1].arg_ptr.arg_str = str;
2065 if (*++s && index("`'\"",*s)) {
2067 s = cpytill(d,s,bufend,term,&len);
2077 while (isascii(*s) && (isalpha(*s) || isdigit(*s) || *s == '_'))
2079 } /* assuming tokenbuf won't clobber */
2084 if (rsfp || !(d=ninstr(s,bufend,d,d+1)))
2085 herewas = str_make(s,bufend-s);
2087 s--, herewas = str_make(s,d-s);
2088 s += herewas->str_cur;
2096 s = cpytill(d,s,bufend,'>',&len);
2101 (isalpha(*d) || isdigit(*d) || *d == '_' || *d == '\''))
2103 if (d - tokenbuf != len) {
2105 arg[1].arg_type = A_GLOB;
2106 d = nsavestr(d,len);
2107 arg[1].arg_ptr.arg_stab = stab = genstab();
2108 stab_io(stab) = stio_new();
2109 stab_val(stab) = str_make(d,len);
2116 (void)strcpy(d,"ARGV");
2118 arg[1].arg_type = A_INDREAD;
2119 arg[1].arg_ptr.arg_stab = stabent(d+1,TRUE);
2122 arg[1].arg_type = A_READ;
2123 arg[1].arg_ptr.arg_stab = stabent(d,TRUE);
2124 if (!stab_io(arg[1].arg_ptr.arg_stab))
2125 stab_io(arg[1].arg_ptr.arg_stab) = stio_new();
2126 if (strEQ(d,"ARGV")) {
2127 (void)aadd(arg[1].arg_ptr.arg_stab);
2128 stab_io(arg[1].arg_ptr.arg_stab)->flags |=
2145 arg[1].arg_type = A_SINGLE;
2152 arg[1].arg_type = A_DOUBLE;
2153 makesingle = TRUE; /* maybe disable runtime scanning */
2154 alwaysdollar = TRUE; /* treat $) and $| as variables */
2159 arg[1].arg_type = A_BACKTICK;
2161 alwaysdollar = TRUE; /* treat $) and $| as variables */
2167 multi_start = curcmd->c_line;
2169 multi_open = multi_close = '<';
2172 if (term && (tmps = index("([{< )]}> )]}>",term)))
2176 tmpstr = Str_new(87,80);
2181 while (s < bufend &&
2182 (*s != term || bcmp(s,tokenbuf,len) != 0) ) {
2187 curcmd->c_line = multi_start;
2188 fatal("EOF in string");
2190 str_nset(tmpstr,d+1,s-d);
2192 str_ncat(herewas,s,bufend-s);
2193 str_replace(linestr,herewas);
2194 oldoldbufptr = oldbufptr = bufptr = s = str_get(linestr);
2195 bufend = linestr->str_ptr + linestr->str_cur;
2199 str_nset(tmpstr,"",0); /* avoid "uninitialized" warning */
2202 s = str_append_till(tmpstr,s+1,bufend,term,leave);
2203 while (s >= bufend) { /* multiple line string? */
2205 !(oldoldbufptr = oldbufptr = s = str_gets(linestr, rsfp, 0))) {
2206 curcmd->c_line = multi_start;
2207 fatal("EOF in string");
2211 STR *str = Str_new(88,0);
2213 str_sset(str,linestr);
2214 astore(stab_xarray(curcmd->c_filestab),
2215 (int)curcmd->c_line,str);
2217 bufend = linestr->str_ptr + linestr->str_cur;
2219 if (*s == term && bcmp(s,tokenbuf,len) == 0) {
2222 str_scat(linestr,herewas);
2223 bufend = linestr->str_ptr + linestr->str_cur;
2227 str_scat(tmpstr,linestr);
2231 s = str_append_till(tmpstr,s,bufend,term,leave);
2233 multi_end = curcmd->c_line;
2235 if (tmpstr->str_cur + 5 < tmpstr->str_len) {
2236 tmpstr->str_len = tmpstr->str_cur + 1;
2237 Renew(tmpstr->str_ptr, tmpstr->str_len, char);
2239 if ((arg[1].arg_type & A_MASK) == A_SINGLE) {
2240 arg[1].arg_ptr.arg_str = tmpstr;
2244 s = tmpstr->str_ptr;
2245 send = s + tmpstr->str_cur;
2246 while (s < send) { /* see if we can make SINGLE */
2247 if (*s == '\\' && s[1] && isdigit(s[1]) && !isdigit(s[2]) &&
2248 !alwaysdollar && s[1] != '0')
2249 *s = '$'; /* grandfather \digit in subst */
2250 if ((*s == '$' || *s == '@') && s+1 < send &&
2251 (alwaysdollar || (s[1] != ')' && s[1] != '|'))) {
2252 makesingle = FALSE; /* force interpretation */
2254 else if (*s == '\\' && s+1 < send) {
2259 s = d = tmpstr->str_ptr; /* assuming shrinkage only */
2261 if ((*s == '$' && s+1 < send &&
2262 (alwaysdollar || /*(*/ (s[1] != ')' && s[1] != '|')) ) ||
2263 (*s == '@' && s+1 < send) ) {
2264 len = scanreg(s,send,tokenbuf) - s;
2265 if (*s == '$' || strEQ(tokenbuf,"ARGV")
2266 || strEQ(tokenbuf,"ENV")
2267 || strEQ(tokenbuf,"SIG")
2268 || strEQ(tokenbuf,"INC") )
2269 (void)stabent(tokenbuf,TRUE); /* make sure it exists */
2274 else if (*s == '\\' && s+1 < send) {
2278 if (!makesingle && (!leave || (*s && index(leave,*s))))
2282 case '0': case '1': case '2': case '3':
2283 case '4': case '5': case '6': case '7':
2285 if (s < send && *s && index("01234567",*s)) {
2289 if (s < send && *s && index("01234567",*s)) {
2318 if ((arg[1].arg_type & A_MASK) == A_DOUBLE && makesingle)
2319 arg[1].arg_type = A_SINGLE; /* now we can optimize on it */
2321 tmpstr->str_cur = d - tmpstr->str_ptr;
2322 arg[1].arg_ptr.arg_str = tmpstr;
2338 register FCMD *fprev = &froot;
2339 register FCMD *fcmd;
2346 Zero(&froot, 1, FCMD);
2348 while (s < bufend || (rsfp && (s = str_gets(linestr,rsfp, 0)) != Nullch)) {
2350 if (in_eval && !rsfp) {
2351 eol = index(s,'\n');
2356 eol = bufend = linestr->str_ptr + linestr->str_cur;
2358 STR *tmpstr = Str_new(89,0);
2360 str_nset(tmpstr, s, eol-s);
2361 astore(stab_xarray(curcmd->c_filestab), (int)curcmd->c_line,tmpstr);
2364 for (t = s+1; *t == ' ' || *t == '\t'; t++) ;
2367 return froot.f_next;
2374 flinebeg = Nullfcmd;
2378 Newz(804,fcmd,1,FCMD);
2379 fprev->f_next = fcmd;
2381 for (t=s; t < eol && *t != '@' && *t != '^'; t++) {
2391 fcmd->f_pre = nsavestr(s, t-s);
2392 fcmd->f_presize = t-s;
2396 fcmd->f_flags |= FC_NOBLANK;
2398 fcmd->f_flags |= FC_REPEAT;
2402 flinebeg = fcmd; /* start values here */
2404 fcmd->f_flags |= FC_CHOP; /* for doing text filling */
2407 fcmd->f_type = F_LINES;
2411 fcmd->f_type = F_LEFT;
2416 fcmd->f_type = F_RIGHT;
2421 fcmd->f_type = F_CENTER;
2427 /* Catch the special case @... and handle it as a string
2429 if (*s == '.' && s[1] == '.') {
2430 goto default_format;
2432 fcmd->f_type = F_DECIMAL;
2436 /* Read a format in the form @####.####, where either group
2437 of ### may be empty, or the final .### may be missing. */
2445 fcmd->f_decimals = s-p;
2446 fcmd->f_flags |= FC_DP;
2448 fcmd->f_decimals = 0;
2454 fcmd->f_type = F_LEFT;
2457 if (fcmd->f_flags & FC_CHOP && *s == '.') {
2458 fcmd->f_flags |= FC_MORE;
2467 (!rsfp || (s = str_gets(linestr, rsfp, 0)) == Nullch) )
2470 if (in_eval && !rsfp) {
2471 eol = index(s,'\n');
2476 eol = bufend = linestr->str_ptr + linestr->str_cur;
2478 STR *tmpstr = Str_new(90,0);
2480 str_nset(tmpstr, s, eol-s);
2481 astore(stab_xarray(curcmd->c_filestab),
2482 (int)curcmd->c_line,tmpstr);
2484 if (strnEQ(s,".\n",2)) {
2486 yyerror("Missing values line");
2487 return froot.f_next;
2493 str = flinebeg->f_unparsed = Str_new(91,eol - s);
2494 str->str_u.str_hash = curstash;
2495 str_nset(str,"(",1);
2496 flinebeg->f_line = curcmd->c_line;
2498 if (!flinebeg->f_next->f_type || index(s, ',')) {
2500 str_ncat(str, s, eol - s - 1);
2501 str_ncat(str,",$$);",5);
2506 while (s < eol && isspace(*s))
2511 case ' ': case '\t': case '\n': case ';':
2512 str_ncat(str, t, s - t);
2513 str_ncat(str, "," ,1);
2514 while (s < eol && (isspace(*s) || *s == ';'))
2519 str_ncat(str, t, s - t);
2521 s = scanreg(s,eol,tokenbuf);
2522 str_ncat(str, t, s - t);
2524 if (s < eol && *s && index("$'\"",*s))
2525 str_ncat(str, ",", 1);
2527 case '"': case '\'':
2528 str_ncat(str, t, s - t);
2531 while (s < eol && (*s != *t || s[-1] == '\\'))
2535 str_ncat(str, t, s - t);
2537 if (s < eol && *s && index("$'\"",*s))
2538 str_ncat(str, ",", 1);
2541 yyerror("Please use commas to separate fields");
2544 str_ncat(str,"$$);",4);
2549 bufptr = str_get(linestr);
2550 yyerror("Format not terminated");
2551 return froot.f_next;
2558 cshlen = strlen(cshname);