This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 4.0 patch 32: patch #20, continued
[perl5.git] / toke.c
CommitLineData
988174c1 1/* $RCSfile: toke.c,v $$Revision: 4.0.1.5 $$Date: 91/11/11 16:45:51 $
a687059c 2 *
d48672a2 3 * Copyright (c) 1991, Larry Wall
a687059c 4 *
d48672a2
LW
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
378cc40b
LW
7 *
8 * $Log: toke.c,v $
988174c1
LW
9 * Revision 4.0.1.5 91/11/11 16:45:51 lwall
10 * patch19: default arg for shift was wrong after first subroutine definition
11 *
de3bb511
LW
12 * Revision 4.0.1.4 91/11/05 19:02:48 lwall
13 * patch11: \x and \c were subject to double interpretation in regexps
14 * patch11: prepared for ctype implementations that don't define isascii()
15 * patch11: nested list operators could miscount parens
16 * patch11: once-thru blocks didn't display right in the debugger
17 * patch11: sort eval "whatever" didn't work
18 * patch11: underscore is now allowed within literal octal and hex numbers
19 *
1462b684
LW
20 * Revision 4.0.1.3 91/06/10 01:32:26 lwall
21 * patch10: m'$foo' now treats string as single quoted
22 * patch10: certain pattern optimizations were botched
23 *
d48672a2
LW
24 * Revision 4.0.1.2 91/06/07 12:05:56 lwall
25 * patch4: new copyright notice
26 * patch4: debugger lost track of lines in eval
27 * patch4: //o and s///o now optimize themselves fully at runtime
28 * patch4: added global modifier for pattern matches
29 *
35c8bce7
LW
30 * Revision 4.0.1.1 91/04/12 09:18:18 lwall
31 * patch1: perl -de "print" wouldn't stop at the first statement
32 *
fe14fcc3
LW
33 * Revision 4.0 91/03/20 01:42:14 lwall
34 * 4.0 baseline.
378cc40b
LW
35 *
36 */
37
38#include "EXTERN.h"
39#include "perl.h"
40#include "perly.h"
41
395c3793
LW
42#ifdef I_FCNTL
43#include <fcntl.h>
44#endif
fe14fcc3
LW
45#ifdef I_SYS_FILE
46#include <sys/file.h>
47#endif
395c3793 48
d48672a2
LW
49#ifdef f_next
50#undef f_next
51#endif
52
395c3793
LW
53/* which backslash sequences to keep in m// or s// */
54
de3bb511 55static char *patleave = "\\.^$@dDwWsSbB+*?|()-nrtfeaxc0123456789[{]}";
395c3793 56
fe14fcc3
LW
57char *reparse; /* if non-null, scanident found ${foo[$bar]} */
58
59void checkcomma();
a687059c 60
ae986130
LW
61#ifdef CLINE
62#undef CLINE
63#endif
e929a76b 64#define CLINE (cmdline = (curcmd->c_line < cmdline ? curcmd->c_line : cmdline))
378cc40b 65
a687059c
LW
66#define META(c) ((c) | 128)
67
378cc40b
LW
68#define RETURN(retval) return (bufptr = s,(int)retval)
69#define OPERATOR(retval) return (expectterm = TRUE,bufptr = s,(int)retval)
70#define TERM(retval) return (CLINE, expectterm = FALSE,bufptr = s,(int)retval)
71#define LOOPX(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)LOOPEX)
378cc40b
LW
72#define FTST(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)FILETEST)
73#define FUN0(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC0)
74#define FUN1(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC1)
75#define FUN2(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC2)
395c3793 76#define FUN2x(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC2x)
378cc40b 77#define FUN3(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC3)
395c3793
LW
78#define FUN4(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC4)
79#define FUN5(f) return(yylval.ival = f,expectterm = FALSE,bufptr = s,(int)FUNC5)
a687059c
LW
80#define FL(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FLIST)
81#define FL2(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FLIST2)
82#define HFUN(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)HSHFUN)
83#define HFUN3(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)HSHFUN3)
84#define LFUN(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LVALFUN)
a687059c
LW
85#define AOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)ADDOP)
86#define MOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)MULOP)
87#define EOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)EQOP)
88#define ROP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)RELOP)
89#define FOP(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP)
90#define FOP2(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP2)
91#define FOP3(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP3)
92#define FOP4(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP4)
93#define FOP22(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP22)
94#define FOP25(f) return(yylval.ival=f,expectterm = FALSE,bufptr = s,(int)FILOP25)
95
96/* This bit of chicanery makes a unary function followed by
97 * a parenthesis into a function with one argument, highest precedence.
98 */
99#define UNI(f) return(yylval.ival = f,expectterm = TRUE,bufptr = s, \
100 (*s == '(' || (s = skipspace(s), *s == '(') ? (int)FUNC1 : (int)UNIOP) )
101
102/* This does similarly for list operators, merely by pretending that the
103 * paren came before the listop rather than after.
104 */
35c8bce7 105#define LOP(f) return(CLINE, *s == '(' || (s = skipspace(s), *s == '(') ? \
de3bb511 106 (*s = (char) META('('), bufptr = oldbufptr, '(') : \
a687059c 107 (yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LISTOP))
9f68db38
LW
108/* grandfather return to old style */
109#define OLDLOP(f) return(yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LISTOP)
a687059c
LW
110
111char *
112skipspace(s)
113register char *s;
114{
de3bb511 115 while (s < bufend && isSPACE(*s))
a687059c
LW
116 s++;
117 return s;
118}
378cc40b 119
ffed7fef
LW
120#ifdef CRIPPLED_CC
121
122#undef UNI
123#undef LOP
124#define UNI(f) return uni(f,s)
125#define LOP(f) return lop(f,s)
126
127int
128uni(f,s)
129int f;
130char *s;
131{
132 yylval.ival = f;
133 expectterm = TRUE;
134 bufptr = s;
135 if (*s == '(')
136 return FUNC1;
137 s = skipspace(s);
138 if (*s == '(')
139 return FUNC1;
140 else
141 return UNIOP;
142}
143
144int
145lop(f,s)
146int f;
147char *s;
148{
35c8bce7 149 CLINE;
ffed7fef
LW
150 if (*s != '(')
151 s = skipspace(s);
152 if (*s == '(') {
153 *s = META('(');
154 bufptr = oldbufptr;
155 return '(';
156 }
157 else {
158 yylval.ival=f;
159 expectterm = TRUE;
160 bufptr = s;
161 return LISTOP;
162 }
163}
164
165#endif /* CRIPPLED_CC */
166
378cc40b
LW
167yylex()
168{
169 register char *s = bufptr;
170 register char *d;
171 register int tmp;
172 static bool in_format = FALSE;
173 static bool firstline = TRUE;
a687059c
LW
174 extern int yychar; /* last token */
175
176 oldoldbufptr = oldbufptr;
177 oldbufptr = s;
378cc40b
LW
178
179 retry:
180#ifdef YYDEBUG
ae986130 181 if (debug & 1)
378cc40b
LW
182 if (index(s,'\n'))
183 fprintf(stderr,"Tokener at %s",s);
184 else
185 fprintf(stderr,"Tokener at %s\n",s);
186#endif
e929a76b
LW
187#ifdef BADSWITCH
188 if (*s & 128) {
de3bb511 189 if ((*s & 127) == '(') {
e929a76b 190 *s++ = '(';
de3bb511
LW
191 oldbufptr = s;
192 }
e929a76b 193 else
fe14fcc3 194 warn("Unrecognized character \\%03o ignored", *s++ & 255);
e929a76b
LW
195 goto retry;
196 }
197#endif
378cc40b
LW
198 switch (*s) {
199 default:
de3bb511 200 if ((*s & 127) == '(') {
a687059c 201 *s++ = '(';
de3bb511
LW
202 oldbufptr = s;
203 }
a687059c 204 else
fe14fcc3 205 warn("Unrecognized character \\%03o ignored", *s++ & 255);
378cc40b 206 goto retry;
e929a76b
LW
207 case 4:
208 case 26:
209 goto fake_eof; /* emulate EOF on ^D or ^Z */
378cc40b 210 case 0:
378cc40b
LW
211 if (!rsfp)
212 RETURN(0);
a687059c
LW
213 if (s++ < bufend)
214 goto retry; /* ignore stray nulls */
215 if (firstline) {
216 firstline = FALSE;
217 if (minus_n || minus_p || perldb) {
218 str_set(linestr,"");
395c3793
LW
219 if (perldb) {
220 char *getenv();
221 char *pdb = getenv("PERLDB");
222
223 str_cat(linestr, pdb ? pdb : "require 'perldb.pl'");
224 str_cat(linestr, ";");
225 }
a687059c
LW
226 if (minus_n || minus_p) {
227 str_cat(linestr,"line: while (<>) {");
fe14fcc3
LW
228 if (minus_l)
229 str_cat(linestr,"chop;");
a687059c
LW
230 if (minus_a)
231 str_cat(linestr,"@F=split(' ');");
232 }
233 oldoldbufptr = oldbufptr = s = str_get(linestr);
234 bufend = linestr->str_ptr + linestr->str_cur;
235 goto retry;
236 }
237 }
378cc40b 238 if (in_format) {
0f85fab0 239 bufptr = bufend;
a687059c 240 yylval.formval = load_format();
378cc40b 241 in_format = FALSE;
a687059c
LW
242 oldoldbufptr = oldbufptr = s = str_get(linestr) + 1;
243 bufend = linestr->str_ptr + linestr->str_cur;
e929a76b
LW
244 OPERATOR(FORMLIST);
245 }
246 curcmd->c_line++;
247#ifdef CRYPTSCRIPT
248 cryptswitch();
249#endif /* CRYPTSCRIPT */
250 do {
251 if ((s = str_gets(linestr, rsfp, 0)) == Nullch) {
252 fake_eof:
395c3793
LW
253 if (rsfp) {
254 if (preprocess)
255 (void)mypclose(rsfp);
de3bb511 256 else if ((FILE*)rsfp == stdin)
395c3793
LW
257 clearerr(stdin);
258 else
259 (void)fclose(rsfp);
260 rsfp = Nullfp;
261 }
e929a76b
LW
262 if (minus_n || minus_p) {
263 str_set(linestr,minus_p ? ";}continue{print" : "");
264 str_cat(linestr,";}");
265 oldoldbufptr = oldbufptr = s = str_get(linestr);
266 bufend = linestr->str_ptr + linestr->str_cur;
267 minus_n = minus_p = 0;
268 goto retry;
269 }
a687059c 270 oldoldbufptr = oldbufptr = s = str_get(linestr);
e929a76b
LW
271 str_set(linestr,"");
272 RETURN(';'); /* not infinite loop because rsfp is NULL now */
378cc40b 273 }
e929a76b
LW
274 if (doextract && *linestr->str_ptr == '#')
275 doextract = FALSE;
276 } while (doextract);
a687059c
LW
277 oldoldbufptr = oldbufptr = bufptr = s;
278 if (perldb) {
279 STR *str = Str_new(85,0);
280
281 str_sset(str,linestr);
395c3793 282 astore(stab_xarray(curcmd->c_filestab),(int)curcmd->c_line,str);
a687059c 283 }
378cc40b 284#ifdef DEBUG
a687059c 285 if (firstline) {
378cc40b
LW
286 char *showinput();
287 s = showinput();
288 }
289#endif
a687059c 290 bufend = linestr->str_ptr + linestr->str_cur;
e929a76b 291 if (curcmd->c_line == 1) {
9f68db38
LW
292 if (*s == '#' && s[1] == '!') {
293 if (!in_eval && !instr(s,"perl") && instr(origargv[0],"perl")) {
294 char **newargv;
295 char *cmd;
296
297 s += 2;
298 if (*s == ' ')
299 s++;
300 cmd = s;
de3bb511 301 while (s < bufend && !isSPACE(*s))
9f68db38
LW
302 s++;
303 *s++ = '\0';
de3bb511 304 while (s < bufend && isSPACE(*s))
9f68db38
LW
305 s++;
306 if (s < bufend) {
307 Newz(899,newargv,origargc+3,char*);
308 newargv[1] = s;
de3bb511 309 while (s < bufend && !isSPACE(*s))
9f68db38
LW
310 s++;
311 *s = '\0';
312 Copy(origargv+1, newargv+2, origargc+1, char*);
313 }
314 else
315 newargv = origargv;
316 newargv[0] = cmd;
317 execv(cmd,newargv);
318 fatal("Can't exec %s", cmd);
319 }
320 }
321 else {
de3bb511 322 while (s < bufend && isSPACE(*s))
9f68db38
LW
323 s++;
324 if (*s == ':') /* for csh's that have to exec sh scripts */
325 s++;
326 }
ae986130 327 }
378cc40b 328 goto retry;
fe14fcc3 329 case ' ': case '\t': case '\f': case '\r': case 013:
378cc40b
LW
330 s++;
331 goto retry;
378cc40b
LW
332 case '#':
333 if (preprocess && s == str_get(linestr) &&
de3bb511
LW
334 s[1] == ' ' && (isDIGIT(s[2]) || strnEQ(s+2,"line ",5)) ) {
335 while (*s && !isDIGIT(*s))
336 s++;
337 curcmd->c_line = atoi(s)-1;
338 while (isDIGIT(*s))
339 s++;
a687059c 340 d = bufend;
de3bb511 341 while (s < d && isSPACE(*s)) s++;
378cc40b
LW
342 s[strlen(s)-1] = '\0'; /* wipe out newline */
343 if (*s == '"') {
344 s++;
345 s[strlen(s)-1] = '\0'; /* wipe out trailing quote */
346 }
347 if (*s)
395c3793 348 curcmd->c_filestab = fstab(s);
378cc40b 349 else
395c3793 350 curcmd->c_filestab = fstab(origfilename);
a687059c 351 oldoldbufptr = oldbufptr = s = str_get(linestr);
378cc40b 352 }
e929a76b
LW
353 /* FALL THROUGH */
354 case '\n':
a687059c
LW
355 if (in_eval && !rsfp) {
356 d = bufend;
357 while (s < d && *s != '\n')
378cc40b 358 s++;
0f85fab0 359 if (s < d)
378cc40b 360 s++;
0f85fab0
LW
361 if (in_format) {
362 bufptr = s;
363 yylval.formval = load_format();
364 in_format = FALSE;
365 oldoldbufptr = oldbufptr = s = bufptr + 1;
366 TERM(FORMLIST);
a687059c 367 }
e929a76b 368 curcmd->c_line++;
378cc40b 369 }
a687059c 370 else {
378cc40b 371 *s = '\0';
a687059c
LW
372 bufend = s;
373 }
378cc40b
LW
374 goto retry;
375 case '-':
de3bb511 376 if (s[1] && isALPHA(s[1]) && !isALPHA(s[2])) {
378cc40b
LW
377 s++;
378 switch (*s++) {
379 case 'r': FTST(O_FTEREAD);
380 case 'w': FTST(O_FTEWRITE);
381 case 'x': FTST(O_FTEEXEC);
382 case 'o': FTST(O_FTEOWNED);
383 case 'R': FTST(O_FTRREAD);
384 case 'W': FTST(O_FTRWRITE);
385 case 'X': FTST(O_FTREXEC);
386 case 'O': FTST(O_FTROWNED);
387 case 'e': FTST(O_FTIS);
388 case 'z': FTST(O_FTZERO);
389 case 's': FTST(O_FTSIZE);
390 case 'f': FTST(O_FTFILE);
391 case 'd': FTST(O_FTDIR);
392 case 'l': FTST(O_FTLINK);
393 case 'p': FTST(O_FTPIPE);
394 case 'S': FTST(O_FTSOCK);
395 case 'u': FTST(O_FTSUID);
396 case 'g': FTST(O_FTSGID);
397 case 'k': FTST(O_FTSVTX);
398 case 'b': FTST(O_FTBLK);
399 case 'c': FTST(O_FTCHR);
400 case 't': FTST(O_FTTTY);
401 case 'T': FTST(O_FTTEXT);
402 case 'B': FTST(O_FTBINARY);
395c3793
LW
403 case 'M': stabent("\024",TRUE); FTST(O_FTMTIME);
404 case 'A': stabent("\024",TRUE); FTST(O_FTATIME);
405 case 'C': stabent("\024",TRUE); FTST(O_FTCTIME);
378cc40b
LW
406 default:
407 s -= 2;
408 break;
409 }
410 }
a687059c
LW
411 tmp = *s++;
412 if (*s == tmp) {
413 s++;
414 RETURN(DEC);
415 }
416 if (expectterm)
417 OPERATOR('-');
418 else
419 AOP(O_SUBTRACT);
378cc40b 420 case '+':
a687059c
LW
421 tmp = *s++;
422 if (*s == tmp) {
378cc40b 423 s++;
a687059c 424 RETURN(INC);
378cc40b 425 }
a687059c
LW
426 if (expectterm)
427 OPERATOR('+');
428 else
429 AOP(O_ADD);
430
378cc40b 431 case '*':
a687059c 432 if (expectterm) {
fe14fcc3 433 s = scanident(s,bufend,tokenbuf);
a687059c
LW
434 yylval.stabval = stabent(tokenbuf,TRUE);
435 TERM(STAR);
436 }
437 tmp = *s++;
438 if (*s == tmp) {
439 s++;
440 OPERATOR(POW);
441 }
442 MOP(O_MULTIPLY);
378cc40b 443 case '%':
a687059c 444 if (expectterm) {
fe14fcc3 445 s = scanident(s,bufend,tokenbuf);
6eb13c3b 446 yylval.stabval = hadd(stabent(tokenbuf,TRUE));
a687059c
LW
447 TERM(HSH);
448 }
449 s++;
450 MOP(O_MODULO);
451
378cc40b
LW
452 case '^':
453 case '~':
454 case '(':
455 case ',':
456 case ':':
457 case '[':
458 tmp = *s++;
459 OPERATOR(tmp);
460 case '{':
461 tmp = *s++;
de3bb511
LW
462 yylval.ival = curcmd->c_line;
463 if (isSPACE(*s) || *s == '#')
378cc40b
LW
464 cmdline = NOLINE; /* invalidate current command line number */
465 OPERATOR(tmp);
466 case ';':
e929a76b
LW
467 if (curcmd->c_line < cmdline)
468 cmdline = curcmd->c_line;
378cc40b
LW
469 tmp = *s++;
470 OPERATOR(tmp);
471 case ')':
472 case ']':
473 tmp = *s++;
474 TERM(tmp);
475 case '}':
476 tmp = *s++;
ffed7fef 477 RETURN(tmp);
378cc40b
LW
478 case '&':
479 s++;
480 tmp = *s++;
481 if (tmp == '&')
482 OPERATOR(ANDAND);
483 s--;
a687059c
LW
484 if (expectterm) {
485 d = bufend;
de3bb511 486 while (s < d && isSPACE(*s))
a687059c 487 s++;
de3bb511 488 if (isALPHA(*s) || *s == '_' || *s == '\'')
a687059c
LW
489 *(--s) = '\\'; /* force next ident to WORD */
490 OPERATOR(AMPER);
491 }
378cc40b
LW
492 OPERATOR('&');
493 case '|':
494 s++;
495 tmp = *s++;
496 if (tmp == '|')
497 OPERATOR(OROR);
498 s--;
499 OPERATOR('|');
500 case '=':
501 s++;
502 tmp = *s++;
503 if (tmp == '=')
a687059c 504 EOP(O_EQ);
378cc40b
LW
505 if (tmp == '~')
506 OPERATOR(MATCH);
507 s--;
508 OPERATOR('=');
509 case '!':
510 s++;
511 tmp = *s++;
512 if (tmp == '=')
a687059c 513 EOP(O_NE);
378cc40b
LW
514 if (tmp == '~')
515 OPERATOR(NMATCH);
516 s--;
517 OPERATOR('!');
518 case '<':
519 if (expectterm) {
520 s = scanstr(s);
521 TERM(RSTRING);
522 }
523 s++;
524 tmp = *s++;
525 if (tmp == '<')
526 OPERATOR(LS);
395c3793
LW
527 if (tmp == '=') {
528 tmp = *s++;
529 if (tmp == '>')
530 EOP(O_NCMP);
531 s--;
a687059c 532 ROP(O_LE);
395c3793 533 }
378cc40b 534 s--;
a687059c 535 ROP(O_LT);
378cc40b
LW
536 case '>':
537 s++;
538 tmp = *s++;
539 if (tmp == '>')
540 OPERATOR(RS);
541 if (tmp == '=')
a687059c 542 ROP(O_GE);
378cc40b 543 s--;
a687059c 544 ROP(O_GT);
378cc40b
LW
545
546#define SNARFWORD \
547 d = tokenbuf; \
de3bb511 548 while (isALNUM(*s) || *s == '\'') \
378cc40b 549 *d++ = *s++; \
663a0e37 550 while (d[-1] == '\'') \
a687059c 551 d--,s--; \
378cc40b
LW
552 *d = '\0'; \
553 d = tokenbuf;
554
555 case '$':
de3bb511 556 if (s[1] == '#' && (isALPHA(s[2]) || s[2] == '_')) {
378cc40b 557 s++;
fe14fcc3 558 s = scanident(s,bufend,tokenbuf);
378cc40b
LW
559 yylval.stabval = aadd(stabent(tokenbuf,TRUE));
560 TERM(ARYLEN);
561 }
a687059c 562 d = s;
fe14fcc3 563 s = scanident(s,bufend,tokenbuf);
a687059c
LW
564 if (reparse) { /* turn ${foo[bar]} into ($foo[bar]) */
565 do_reparse:
566 s[-1] = ')';
567 s = d;
568 s[1] = s[0];
569 s[0] = '(';
570 goto retry;
571 }
378cc40b
LW
572 yylval.stabval = stabent(tokenbuf,TRUE);
573 TERM(REG);
574
575 case '@':
a687059c 576 d = s;
fe14fcc3 577 s = scanident(s,bufend,tokenbuf);
a687059c
LW
578 if (reparse)
579 goto do_reparse;
e929a76b 580 yylval.stabval = aadd(stabent(tokenbuf,TRUE));
378cc40b
LW
581 TERM(ARY);
582
583 case '/': /* may either be division or pattern */
584 case '?': /* may either be conditional or pattern */
585 if (expectterm) {
586 s = scanpat(s);
587 TERM(PATTERN);
588 }
589 tmp = *s++;
a687059c
LW
590 if (tmp == '/')
591 MOP(O_DIVIDE);
378cc40b
LW
592 OPERATOR(tmp);
593
594 case '.':
de3bb511 595 if (!expectterm || !isDIGIT(s[1])) {
378cc40b 596 tmp = *s++;
a687059c
LW
597 if (*s == tmp) {
598 s++;
378cc40b 599 OPERATOR(DOTDOT);
a687059c
LW
600 }
601 AOP(O_CONCAT);
378cc40b
LW
602 }
603 /* FALL THROUGH */
604 case '0': case '1': case '2': case '3': case '4':
605 case '5': case '6': case '7': case '8': case '9':
606 case '\'': case '"': case '`':
607 s = scanstr(s);
608 TERM(RSTRING);
609
a687059c
LW
610 case '\\': /* some magic to force next word to be a WORD */
611 s++; /* used by do and sub to force a separate namespace */
612 /* FALL THROUGH */
378cc40b
LW
613 case '_':
614 SNARFWORD;
e929a76b
LW
615 if (d[1] == '_') {
616 if (strEQ(d,"__LINE__") || strEQ(d,"__FILE__")) {
617 ARG *arg = op_new(1);
618
619 yylval.arg = arg;
620 arg->arg_type = O_ITEM;
621 if (d[2] == 'L')
622 (void)sprintf(tokenbuf,"%ld",(long)curcmd->c_line);
623 else
395c3793 624 strcpy(tokenbuf, stab_val(curcmd->c_filestab)->str_ptr);
e929a76b
LW
625 arg[1].arg_type = A_SINGLE;
626 arg[1].arg_ptr.arg_str = str_make(tokenbuf,strlen(tokenbuf));
627 TERM(RSTRING);
628 }
395c3793
LW
629 else if (strEQ(d,"__END__")) {
630#ifndef TAINT
631 STAB *stab;
632 int fd;
633
de3bb511 634 /*SUPPRESS 560*/
395c3793
LW
635 if (stab = stabent("DATA",FALSE)) {
636 stab->str_pok |= SP_MULTI;
637 stab_io(stab) = stio_new();
638 stab_io(stab)->ifp = rsfp;
fe14fcc3 639#if defined(HAS_FCNTL) && defined(F_SETFD)
395c3793
LW
640 fd = fileno(rsfp);
641 fcntl(fd,F_SETFD,fd >= 3);
642#endif
643 if (preprocess)
644 stab_io(stab)->type = '|';
de3bb511 645 else if ((FILE*)rsfp == stdin)
395c3793
LW
646 stab_io(stab)->type = '-';
647 else
648 stab_io(stab)->type = '<';
649 rsfp = Nullfp;
650 }
651#endif
e929a76b 652 goto fake_eof;
395c3793 653 }
e929a76b 654 }
a687059c 655 break;
378cc40b
LW
656 case 'a': case 'A':
657 SNARFWORD;
34de22dd
LW
658 if (strEQ(d,"alarm"))
659 UNI(O_ALARM);
a687059c
LW
660 if (strEQ(d,"accept"))
661 FOP22(O_ACCEPT);
662 if (strEQ(d,"atan2"))
663 FUN2(O_ATAN2);
664 break;
378cc40b
LW
665 case 'b': case 'B':
666 SNARFWORD;
a687059c
LW
667 if (strEQ(d,"bind"))
668 FOP2(O_BIND);
0f85fab0
LW
669 if (strEQ(d,"binmode"))
670 FOP(O_BINMODE);
a687059c 671 break;
378cc40b
LW
672 case 'c': case 'C':
673 SNARFWORD;
a687059c
LW
674 if (strEQ(d,"chop"))
675 LFUN(O_CHOP);
378cc40b
LW
676 if (strEQ(d,"continue"))
677 OPERATOR(CONTINUE);
9f68db38
LW
678 if (strEQ(d,"chdir")) {
679 (void)stabent("ENV",TRUE); /* may use HOME */
378cc40b 680 UNI(O_CHDIR);
9f68db38 681 }
378cc40b 682 if (strEQ(d,"close"))
a687059c
LW
683 FOP(O_CLOSE);
684 if (strEQ(d,"closedir"))
685 FOP(O_CLOSEDIR);
395c3793
LW
686 if (strEQ(d,"cmp"))
687 EOP(O_SCMP);
688 if (strEQ(d,"caller"))
689 UNI(O_CALLER);
a687059c
LW
690 if (strEQ(d,"crypt")) {
691#ifdef FCRYPT
de3bb511
LW
692 static int cryptseen = 0;
693
694 if (!cryptseen++)
695 init_des();
a687059c 696#endif
378cc40b 697 FUN2(O_CRYPT);
378cc40b 698 }
a687059c
LW
699 if (strEQ(d,"chmod"))
700 LOP(O_CHMOD);
701 if (strEQ(d,"chown"))
702 LOP(O_CHOWN);
703 if (strEQ(d,"connect"))
704 FOP2(O_CONNECT);
705 if (strEQ(d,"cos"))
706 UNI(O_COS);
707 if (strEQ(d,"chroot"))
708 UNI(O_CHROOT);
709 break;
378cc40b
LW
710 case 'd': case 'D':
711 SNARFWORD;
a687059c
LW
712 if (strEQ(d,"do")) {
713 d = bufend;
de3bb511 714 while (s < d && isSPACE(*s))
a687059c 715 s++;
de3bb511 716 if (isALPHA(*s) || *s == '_')
a687059c 717 *(--s) = '\\'; /* force next ident to WORD */
378cc40b 718 OPERATOR(DO);
a687059c 719 }
378cc40b 720 if (strEQ(d,"die"))
a687059c
LW
721 LOP(O_DIE);
722 if (strEQ(d,"defined"))
723 LFUN(O_DEFINED);
378cc40b
LW
724 if (strEQ(d,"delete"))
725 OPERATOR(DELETE);
a687059c
LW
726 if (strEQ(d,"dbmopen"))
727 HFUN3(O_DBMOPEN);
728 if (strEQ(d,"dbmclose"))
729 HFUN(O_DBMCLOSE);
730 if (strEQ(d,"dump"))
731 LOOPX(O_DUMP);
732 break;
378cc40b
LW
733 case 'e': case 'E':
734 SNARFWORD;
735 if (strEQ(d,"else"))
736 OPERATOR(ELSE);
737 if (strEQ(d,"elsif")) {
e929a76b 738 yylval.ival = curcmd->c_line;
378cc40b
LW
739 OPERATOR(ELSIF);
740 }
741 if (strEQ(d,"eq") || strEQ(d,"EQ"))
a687059c 742 EOP(O_SEQ);
378cc40b
LW
743 if (strEQ(d,"exit"))
744 UNI(O_EXIT);
745 if (strEQ(d,"eval")) {
746 allstabs = TRUE; /* must initialize everything since */
747 UNI(O_EVAL); /* we don't know what will be used */
748 }
749 if (strEQ(d,"eof"))
a687059c 750 FOP(O_EOF);
378cc40b 751 if (strEQ(d,"exp"))
a687059c 752 UNI(O_EXP);
378cc40b 753 if (strEQ(d,"each"))
a687059c 754 HFUN(O_EACH);
378cc40b 755 if (strEQ(d,"exec")) {
a687059c 756 set_csh();
395c3793 757 LOP(O_EXEC_OP);
378cc40b 758 }
a687059c
LW
759 if (strEQ(d,"endhostent"))
760 FUN0(O_EHOSTENT);
761 if (strEQ(d,"endnetent"))
762 FUN0(O_ENETENT);
763 if (strEQ(d,"endservent"))
764 FUN0(O_ESERVENT);
765 if (strEQ(d,"endprotoent"))
766 FUN0(O_EPROTOENT);
767 if (strEQ(d,"endpwent"))
768 FUN0(O_EPWENT);
769 if (strEQ(d,"endgrent"))
770 FUN0(O_EGRENT);
771 break;
378cc40b
LW
772 case 'f': case 'F':
773 SNARFWORD;
9f68db38 774 if (strEQ(d,"for") || strEQ(d,"foreach")) {
e929a76b 775 yylval.ival = curcmd->c_line;
378cc40b 776 OPERATOR(FOR);
9f68db38 777 }
378cc40b 778 if (strEQ(d,"format")) {
a687059c 779 d = bufend;
de3bb511 780 while (s < d && isSPACE(*s))
a687059c 781 s++;
de3bb511 782 if (isALPHA(*s) || *s == '_')
a687059c 783 *(--s) = '\\'; /* force next ident to WORD */
378cc40b 784 in_format = TRUE;
a687059c
LW
785 allstabs = TRUE; /* must initialize everything since */
786 OPERATOR(FORMAT); /* we don't know what will be used */
378cc40b
LW
787 }
788 if (strEQ(d,"fork"))
789 FUN0(O_FORK);
a687059c
LW
790 if (strEQ(d,"fcntl"))
791 FOP3(O_FCNTL);
792 if (strEQ(d,"fileno"))
793 FOP(O_FILENO);
794 if (strEQ(d,"flock"))
795 FOP2(O_FLOCK);
796 break;
378cc40b
LW
797 case 'g': case 'G':
798 SNARFWORD;
799 if (strEQ(d,"gt") || strEQ(d,"GT"))
a687059c 800 ROP(O_SGT);
378cc40b 801 if (strEQ(d,"ge") || strEQ(d,"GE"))
a687059c
LW
802 ROP(O_SGE);
803 if (strEQ(d,"grep"))
804 FL2(O_GREP);
378cc40b
LW
805 if (strEQ(d,"goto"))
806 LOOPX(O_GOTO);
807 if (strEQ(d,"gmtime"))
a687059c
LW
808 UNI(O_GMTIME);
809 if (strEQ(d,"getc"))
810 FOP(O_GETC);
811 if (strnEQ(d,"get",3)) {
812 d += 3;
813 if (*d == 'p') {
814 if (strEQ(d,"ppid"))
815 FUN0(O_GETPPID);
816 if (strEQ(d,"pgrp"))
817 UNI(O_GETPGRP);
818 if (strEQ(d,"priority"))
819 FUN2(O_GETPRIORITY);
820 if (strEQ(d,"protobyname"))
821 UNI(O_GPBYNAME);
822 if (strEQ(d,"protobynumber"))
823 FUN1(O_GPBYNUMBER);
824 if (strEQ(d,"protoent"))
825 FUN0(O_GPROTOENT);
826 if (strEQ(d,"pwent"))
827 FUN0(O_GPWENT);
828 if (strEQ(d,"pwnam"))
829 FUN1(O_GPWNAM);
830 if (strEQ(d,"pwuid"))
831 FUN1(O_GPWUID);
832 if (strEQ(d,"peername"))
833 FOP(O_GETPEERNAME);
834 }
835 else if (*d == 'h') {
836 if (strEQ(d,"hostbyname"))
837 UNI(O_GHBYNAME);
838 if (strEQ(d,"hostbyaddr"))
839 FUN2(O_GHBYADDR);
840 if (strEQ(d,"hostent"))
841 FUN0(O_GHOSTENT);
842 }
843 else if (*d == 'n') {
844 if (strEQ(d,"netbyname"))
845 UNI(O_GNBYNAME);
846 if (strEQ(d,"netbyaddr"))
847 FUN2(O_GNBYADDR);
848 if (strEQ(d,"netent"))
849 FUN0(O_GNETENT);
850 }
851 else if (*d == 's') {
852 if (strEQ(d,"servbyname"))
853 FUN2(O_GSBYNAME);
854 if (strEQ(d,"servbyport"))
855 FUN2(O_GSBYPORT);
856 if (strEQ(d,"servent"))
857 FUN0(O_GSERVENT);
858 if (strEQ(d,"sockname"))
859 FOP(O_GETSOCKNAME);
860 if (strEQ(d,"sockopt"))
861 FOP3(O_GSOCKOPT);
862 }
863 else if (*d == 'g') {
864 if (strEQ(d,"grent"))
865 FUN0(O_GGRENT);
866 if (strEQ(d,"grnam"))
867 FUN1(O_GGRNAM);
868 if (strEQ(d,"grgid"))
869 FUN1(O_GGRGID);
870 }
871 else if (*d == 'l') {
872 if (strEQ(d,"login"))
873 FUN0(O_GETLOGIN);
874 }
875 d -= 3;
876 }
877 break;
378cc40b
LW
878 case 'h': case 'H':
879 SNARFWORD;
880 if (strEQ(d,"hex"))
a687059c
LW
881 UNI(O_HEX);
882 break;
378cc40b
LW
883 case 'i': case 'I':
884 SNARFWORD;
885 if (strEQ(d,"if")) {
e929a76b 886 yylval.ival = curcmd->c_line;
378cc40b
LW
887 OPERATOR(IF);
888 }
889 if (strEQ(d,"index"))
395c3793 890 FUN2x(O_INDEX);
378cc40b 891 if (strEQ(d,"int"))
a687059c
LW
892 UNI(O_INT);
893 if (strEQ(d,"ioctl"))
894 FOP3(O_IOCTL);
895 break;
378cc40b
LW
896 case 'j': case 'J':
897 SNARFWORD;
898 if (strEQ(d,"join"))
a687059c
LW
899 FL2(O_JOIN);
900 break;
378cc40b
LW
901 case 'k': case 'K':
902 SNARFWORD;
903 if (strEQ(d,"keys"))
a687059c
LW
904 HFUN(O_KEYS);
905 if (strEQ(d,"kill"))
906 LOP(O_KILL);
907 break;
378cc40b
LW
908 case 'l': case 'L':
909 SNARFWORD;
910 if (strEQ(d,"last"))
911 LOOPX(O_LAST);
912 if (strEQ(d,"local"))
913 OPERATOR(LOCAL);
914 if (strEQ(d,"length"))
a687059c 915 UNI(O_LENGTH);
378cc40b 916 if (strEQ(d,"lt") || strEQ(d,"LT"))
a687059c 917 ROP(O_SLT);
378cc40b 918 if (strEQ(d,"le") || strEQ(d,"LE"))
a687059c 919 ROP(O_SLE);
378cc40b 920 if (strEQ(d,"localtime"))
a687059c 921 UNI(O_LOCALTIME);
378cc40b 922 if (strEQ(d,"log"))
a687059c 923 UNI(O_LOG);
378cc40b
LW
924 if (strEQ(d,"link"))
925 FUN2(O_LINK);
a687059c
LW
926 if (strEQ(d,"listen"))
927 FOP2(O_LISTEN);
928 if (strEQ(d,"lstat"))
929 FOP(O_LSTAT);
930 break;
378cc40b 931 case 'm': case 'M':
663a0e37
LW
932 if (s[1] == '\'') {
933 d = "m";
934 s++;
935 }
936 else {
937 SNARFWORD;
938 }
378cc40b
LW
939 if (strEQ(d,"m")) {
940 s = scanpat(s-1);
a687059c
LW
941 if (yylval.arg)
942 TERM(PATTERN);
943 else
944 RETURN(1); /* force error */
378cc40b 945 }
395c3793
LW
946 switch (d[1]) {
947 case 'k':
948 if (strEQ(d,"mkdir"))
949 FUN2(O_MKDIR);
950 break;
951 case 's':
952 if (strEQ(d,"msgctl"))
953 FUN3(O_MSGCTL);
954 if (strEQ(d,"msgget"))
955 FUN2(O_MSGGET);
956 if (strEQ(d,"msgrcv"))
957 FUN5(O_MSGRCV);
958 if (strEQ(d,"msgsnd"))
959 FUN3(O_MSGSND);
960 break;
961 }
a687059c 962 break;
378cc40b
LW
963 case 'n': case 'N':
964 SNARFWORD;
965 if (strEQ(d,"next"))
966 LOOPX(O_NEXT);
967 if (strEQ(d,"ne") || strEQ(d,"NE"))
a687059c
LW
968 EOP(O_SNE);
969 break;
378cc40b
LW
970 case 'o': case 'O':
971 SNARFWORD;
972 if (strEQ(d,"open"))
973 OPERATOR(OPEN);
974 if (strEQ(d,"ord"))
a687059c 975 UNI(O_ORD);
378cc40b 976 if (strEQ(d,"oct"))
a687059c
LW
977 UNI(O_OCT);
978 if (strEQ(d,"opendir"))
d48672a2 979 FOP2(O_OPEN_DIR);
a687059c 980 break;
378cc40b
LW
981 case 'p': case 'P':
982 SNARFWORD;
983 if (strEQ(d,"print")) {
a687059c
LW
984 checkcomma(s,"filehandle");
985 LOP(O_PRINT);
378cc40b
LW
986 }
987 if (strEQ(d,"printf")) {
a687059c
LW
988 checkcomma(s,"filehandle");
989 LOP(O_PRTF);
378cc40b
LW
990 }
991 if (strEQ(d,"push")) {
992 yylval.ival = O_PUSH;
993 OPERATOR(PUSH);
994 }
995 if (strEQ(d,"pop"))
996 OPERATOR(POP);
a687059c
LW
997 if (strEQ(d,"pack"))
998 FL2(O_PACK);
999 if (strEQ(d,"package"))
1000 OPERATOR(PACKAGE);
9f68db38
LW
1001 if (strEQ(d,"pipe"))
1002 FOP22(O_PIPE);
a687059c 1003 break;
378cc40b
LW
1004 case 'q': case 'Q':
1005 SNARFWORD;
a687059c
LW
1006 if (strEQ(d,"q")) {
1007 s = scanstr(s-1);
1008 TERM(RSTRING);
1009 }
1010 if (strEQ(d,"qq")) {
1011 s = scanstr(s-2);
1012 TERM(RSTRING);
1013 }
fe14fcc3
LW
1014 if (strEQ(d,"qx")) {
1015 s = scanstr(s-2);
1016 TERM(RSTRING);
1017 }
a687059c 1018 break;
378cc40b
LW
1019 case 'r': case 'R':
1020 SNARFWORD;
a687059c 1021 if (strEQ(d,"return"))
9f68db38 1022 OLDLOP(O_RETURN);
e929a76b
LW
1023 if (strEQ(d,"require")) {
1024 allstabs = TRUE; /* must initialize everything since */
1025 UNI(O_REQUIRE); /* we don't know what will be used */
1026 }
378cc40b
LW
1027 if (strEQ(d,"reset"))
1028 UNI(O_RESET);
1029 if (strEQ(d,"redo"))
1030 LOOPX(O_REDO);
1031 if (strEQ(d,"rename"))
1032 FUN2(O_RENAME);
a687059c
LW
1033 if (strEQ(d,"rand"))
1034 UNI(O_RAND);
1035 if (strEQ(d,"rmdir"))
1036 UNI(O_RMDIR);
1037 if (strEQ(d,"rindex"))
395c3793 1038 FUN2x(O_RINDEX);
a687059c
LW
1039 if (strEQ(d,"read"))
1040 FOP3(O_READ);
1041 if (strEQ(d,"readdir"))
1042 FOP(O_READDIR);
1043 if (strEQ(d,"rewinddir"))
1044 FOP(O_REWINDDIR);
1045 if (strEQ(d,"recv"))
1046 FOP4(O_RECV);
1047 if (strEQ(d,"reverse"))
1048 LOP(O_REVERSE);
1049 if (strEQ(d,"readlink"))
1050 UNI(O_READLINK);
1051 break;
378cc40b 1052 case 's': case 'S':
663a0e37
LW
1053 if (s[1] == '\'') {
1054 d = "s";
1055 s++;
1056 }
1057 else {
1058 SNARFWORD;
1059 }
378cc40b
LW
1060 if (strEQ(d,"s")) {
1061 s = scansubst(s);
a687059c
LW
1062 if (yylval.arg)
1063 TERM(SUBST);
1064 else
1065 RETURN(1); /* force error */
1066 }
1067 switch (d[1]) {
1068 case 'a':
1069 case 'b':
395c3793 1070 break;
a687059c 1071 case 'c':
395c3793
LW
1072 if (strEQ(d,"scalar"))
1073 UNI(O_SCALAR);
1074 break;
a687059c
LW
1075 case 'd':
1076 break;
1077 case 'e':
1078 if (strEQ(d,"select"))
e929a76b 1079 OPERATOR(SSELECT);
a687059c
LW
1080 if (strEQ(d,"seek"))
1081 FOP3(O_SEEK);
395c3793
LW
1082 if (strEQ(d,"semctl"))
1083 FUN4(O_SEMCTL);
1084 if (strEQ(d,"semget"))
1085 FUN3(O_SEMGET);
1086 if (strEQ(d,"semop"))
1087 FUN2(O_SEMOP);
a687059c
LW
1088 if (strEQ(d,"send"))
1089 FOP3(O_SEND);
1090 if (strEQ(d,"setpgrp"))
1091 FUN2(O_SETPGRP);
1092 if (strEQ(d,"setpriority"))
1093 FUN3(O_SETPRIORITY);
1094 if (strEQ(d,"sethostent"))
1095 FUN1(O_SHOSTENT);
1096 if (strEQ(d,"setnetent"))
1097 FUN1(O_SNETENT);
1098 if (strEQ(d,"setservent"))
1099 FUN1(O_SSERVENT);
1100 if (strEQ(d,"setprotoent"))
1101 FUN1(O_SPROTOENT);
1102 if (strEQ(d,"setpwent"))
1103 FUN0(O_SPWENT);
1104 if (strEQ(d,"setgrent"))
1105 FUN0(O_SGRENT);
1106 if (strEQ(d,"seekdir"))
1107 FOP2(O_SEEKDIR);
1108 if (strEQ(d,"setsockopt"))
1109 FOP4(O_SSOCKOPT);
1110 break;
1111 case 'f':
1112 case 'g':
1113 break;
1114 case 'h':
1115 if (strEQ(d,"shift"))
1116 TERM(SHIFT);
395c3793
LW
1117 if (strEQ(d,"shmctl"))
1118 FUN3(O_SHMCTL);
1119 if (strEQ(d,"shmget"))
1120 FUN3(O_SHMGET);
1121 if (strEQ(d,"shmread"))
1122 FUN4(O_SHMREAD);
1123 if (strEQ(d,"shmwrite"))
1124 FUN4(O_SHMWRITE);
a687059c
LW
1125 if (strEQ(d,"shutdown"))
1126 FOP2(O_SHUTDOWN);
1127 break;
1128 case 'i':
1129 if (strEQ(d,"sin"))
1130 UNI(O_SIN);
1131 break;
1132 case 'j':
1133 case 'k':
1134 break;
1135 case 'l':
1136 if (strEQ(d,"sleep"))
1137 UNI(O_SLEEP);
1138 break;
1139 case 'm':
1140 case 'n':
1141 break;
1142 case 'o':
1143 if (strEQ(d,"socket"))
1144 FOP4(O_SOCKET);
1145 if (strEQ(d,"socketpair"))
e929a76b 1146 FOP25(O_SOCKPAIR);
a687059c
LW
1147 if (strEQ(d,"sort")) {
1148 checkcomma(s,"subroutine name");
1149 d = bufend;
de3bb511 1150 while (s < d && isSPACE(*s)) s++;
a687059c
LW
1151 if (*s == ';' || *s == ')') /* probably a close */
1152 fatal("sort is now a reserved word");
de3bb511
LW
1153 if (isALPHA(*s) || *s == '_') {
1154 /*SUPPRESS 530*/
1155 for (d = s; isALNUM(*d); d++) ;
03a14243
LW
1156 strncpy(tokenbuf,s,d-s);
1157 if (strNE(tokenbuf,"keys") &&
1158 strNE(tokenbuf,"values") &&
1159 strNE(tokenbuf,"split") &&
1160 strNE(tokenbuf,"grep") &&
1161 strNE(tokenbuf,"readdir") &&
1162 strNE(tokenbuf,"unpack") &&
1163 strNE(tokenbuf,"do") &&
de3bb511
LW
1164 strNE(tokenbuf,"eval") &&
1165 (d >= bufend || isSPACE(*d)) )
a687059c
LW
1166 *(--s) = '\\'; /* force next ident to WORD */
1167 }
1168 LOP(O_SORT);
1169 }
1170 break;
1171 case 'p':
1172 if (strEQ(d,"split"))
1173 TERM(SPLIT);
1174 if (strEQ(d,"sprintf"))
1175 FL(O_SPRINTF);
79a0689e
LW
1176 if (strEQ(d,"splice")) {
1177 yylval.ival = O_SPLICE;
1178 OPERATOR(PUSH);
1179 }
a687059c
LW
1180 break;
1181 case 'q':
1182 if (strEQ(d,"sqrt"))
1183 UNI(O_SQRT);
1184 break;
1185 case 'r':
1186 if (strEQ(d,"srand"))
1187 UNI(O_SRAND);
1188 break;
1189 case 's':
1190 break;
1191 case 't':
1192 if (strEQ(d,"stat"))
1193 FOP(O_STAT);
1194 if (strEQ(d,"study")) {
1195 sawstudy++;
1196 LFUN(O_STUDY);
1197 }
1198 break;
1199 case 'u':
1200 if (strEQ(d,"substr"))
395c3793 1201 FUN2x(O_SUBSTR);
a687059c 1202 if (strEQ(d,"sub")) {
de3bb511 1203 yylval.ival = savestack->ary_fill; /* restore stuff on reduce */
988174c1
LW
1204 savelong(&subline);
1205 saveitem(subname);
de3bb511 1206
e929a76b 1207 subline = curcmd->c_line;
a687059c 1208 d = bufend;
de3bb511 1209 while (s < d && isSPACE(*s))
a687059c 1210 s++;
de3bb511 1211 if (isALPHA(*s) || *s == '_' || *s == '\'') {
988174c1
LW
1212 str_sset(subname,curstname);
1213 str_ncat(subname,"'",1);
1214 for (d = s+1; isALNUM(*d) || *d == '\''; d++)
1215 /*SUPPRESS 530*/
1216 ;
1217 if (d[-1] == '\'')
1218 d--;
1219 str_ncat(subname,s,d-s);
a687059c
LW
1220 *(--s) = '\\'; /* force next ident to WORD */
1221 }
988174c1 1222 else
a687059c
LW
1223 str_set(subname,"?");
1224 OPERATOR(SUB);
1225 }
1226 break;
1227 case 'v':
1228 case 'w':
1229 case 'x':
1230 break;
1231 case 'y':
1232 if (strEQ(d,"system")) {
1233 set_csh();
1234 LOP(O_SYSTEM);
1235 }
1236 if (strEQ(d,"symlink"))
1237 FUN2(O_SYMLINK);
1238 if (strEQ(d,"syscall"))
1239 LOP(O_SYSCALL);
395c3793
LW
1240 if (strEQ(d,"sysread"))
1241 FOP3(O_SYSREAD);
1242 if (strEQ(d,"syswrite"))
1243 FOP3(O_SYSWRITE);
a687059c
LW
1244 break;
1245 case 'z':
1246 break;
1247 }
1248 break;
378cc40b
LW
1249 case 't': case 'T':
1250 SNARFWORD;
1251 if (strEQ(d,"tr")) {
1252 s = scantrans(s);
a687059c
LW
1253 if (yylval.arg)
1254 TERM(TRANS);
1255 else
1256 RETURN(1); /* force error */
378cc40b
LW
1257 }
1258 if (strEQ(d,"tell"))
a687059c
LW
1259 FOP(O_TELL);
1260 if (strEQ(d,"telldir"))
1261 FOP(O_TELLDIR);
378cc40b
LW
1262 if (strEQ(d,"time"))
1263 FUN0(O_TIME);
1264 if (strEQ(d,"times"))
1265 FUN0(O_TMS);
e929a76b
LW
1266 if (strEQ(d,"truncate"))
1267 FOP2(O_TRUNCATE);
a687059c 1268 break;
378cc40b
LW
1269 case 'u': case 'U':
1270 SNARFWORD;
1271 if (strEQ(d,"using"))
1272 OPERATOR(USING);
1273 if (strEQ(d,"until")) {
e929a76b 1274 yylval.ival = curcmd->c_line;
378cc40b
LW
1275 OPERATOR(UNTIL);
1276 }
1277 if (strEQ(d,"unless")) {
e929a76b 1278 yylval.ival = curcmd->c_line;
378cc40b
LW
1279 OPERATOR(UNLESS);
1280 }
a687059c
LW
1281 if (strEQ(d,"unlink"))
1282 LOP(O_UNLINK);
1283 if (strEQ(d,"undef"))
1284 LFUN(O_UNDEF);
1285 if (strEQ(d,"unpack"))
1286 FUN2(O_UNPACK);
1287 if (strEQ(d,"utime"))
1288 LOP(O_UTIME);
378cc40b 1289 if (strEQ(d,"umask"))
a687059c 1290 UNI(O_UMASK);
378cc40b
LW
1291 if (strEQ(d,"unshift")) {
1292 yylval.ival = O_UNSHIFT;
1293 OPERATOR(PUSH);
1294 }
a687059c 1295 break;
378cc40b
LW
1296 case 'v': case 'V':
1297 SNARFWORD;
1298 if (strEQ(d,"values"))
a687059c
LW
1299 HFUN(O_VALUES);
1300 if (strEQ(d,"vec")) {
1301 sawvec = TRUE;
1302 FUN3(O_VEC);
1303 }
1304 break;
378cc40b
LW
1305 case 'w': case 'W':
1306 SNARFWORD;
378cc40b 1307 if (strEQ(d,"while")) {
e929a76b 1308 yylval.ival = curcmd->c_line;
378cc40b
LW
1309 OPERATOR(WHILE);
1310 }
a687059c
LW
1311 if (strEQ(d,"warn"))
1312 LOP(O_WARN);
378cc40b
LW
1313 if (strEQ(d,"wait"))
1314 FUN0(O_WAIT);
395c3793
LW
1315 if (strEQ(d,"waitpid"))
1316 FUN2(O_WAITPID);
a687059c
LW
1317 if (strEQ(d,"wantarray")) {
1318 yylval.arg = op_new(1);
1319 yylval.arg->arg_type = O_ITEM;
1320 yylval.arg[1].arg_type = A_WANTARRAY;
1321 TERM(RSTRING);
1322 }
1323 if (strEQ(d,"write"))
1324 FOP(O_WRITE);
1325 break;
378cc40b
LW
1326 case 'x': case 'X':
1327 SNARFWORD;
1328 if (!expectterm && strEQ(d,"x"))
a687059c
LW
1329 MOP(O_REPEAT);
1330 break;
378cc40b 1331 case 'y': case 'Y':
663a0e37
LW
1332 if (s[1] == '\'') {
1333 d = "y";
1334 s++;
1335 }
1336 else {
1337 SNARFWORD;
1338 }
378cc40b
LW
1339 if (strEQ(d,"y")) {
1340 s = scantrans(s);
1341 TERM(TRANS);
1342 }
a687059c 1343 break;
378cc40b
LW
1344 case 'z': case 'Z':
1345 SNARFWORD;
a687059c
LW
1346 break;
1347 }
1348 yylval.cval = savestr(d);
1349 expectterm = FALSE;
1350 if (oldoldbufptr && oldoldbufptr < bufptr) {
de3bb511 1351 while (isSPACE(*oldoldbufptr))
a687059c
LW
1352 oldoldbufptr++;
1353 if (*oldoldbufptr == 'p' && strnEQ(oldoldbufptr,"print",5))
1354 expectterm = TRUE;
1355 else if (*oldoldbufptr == 's' && strnEQ(oldoldbufptr,"sort",4))
1356 expectterm = TRUE;
1357 }
1358 return (CLINE, bufptr = s, (int)WORD);
1359}
1360
fe14fcc3 1361void
a687059c
LW
1362checkcomma(s,what)
1363register char *s;
1364char *what;
1365{
fe14fcc3 1366 char *someword;
e929a76b 1367
a687059c
LW
1368 if (*s == '(')
1369 s++;
de3bb511 1370 while (s < bufend && isSPACE(*s))
a687059c 1371 s++;
de3bb511 1372 if (isALPHA(*s) || *s == '_') {
fe14fcc3 1373 someword = s++;
de3bb511 1374 while (isALNUM(*s))
a687059c 1375 s++;
de3bb511 1376 while (s < bufend && isSPACE(*s))
a687059c 1377 s++;
e929a76b
LW
1378 if (*s == ',') {
1379 *s = '\0';
fe14fcc3 1380 someword = instr(
e929a76b
LW
1381 "tell eof times getlogin wait length shift umask getppid \
1382 cos exp int log rand sin sqrt ord wantarray",
fe14fcc3 1383 someword);
e929a76b 1384 *s = ',';
fe14fcc3 1385 if (someword)
e929a76b 1386 return;
a687059c 1387 fatal("No comma allowed after %s", what);
e929a76b 1388 }
378cc40b
LW
1389 }
1390}
1391
1392char *
fe14fcc3 1393scanident(s,send,dest)
378cc40b 1394register char *s;
a687059c 1395register char *send;
378cc40b
LW
1396char *dest;
1397{
1398 register char *d;
a687059c 1399 int brackets = 0;
378cc40b 1400
a687059c 1401 reparse = Nullch;
378cc40b
LW
1402 s++;
1403 d = dest;
de3bb511
LW
1404 if (isDIGIT(*s)) {
1405 while (isDIGIT(*s))
378cc40b
LW
1406 *d++ = *s++;
1407 }
1408 else {
de3bb511 1409 while (isALNUM(*s) || *s == '\'')
378cc40b
LW
1410 *d++ = *s++;
1411 }
663a0e37 1412 while (d > dest+1 && d[-1] == '\'')
a687059c 1413 d--,s--;
378cc40b
LW
1414 *d = '\0';
1415 d = dest;
1416 if (!*d) {
1417 *d = *s++;
a687059c 1418 if (*d == '{' /* } */ ) {
378cc40b 1419 d = dest;
a687059c
LW
1420 brackets++;
1421 while (s < send && brackets) {
de3bb511 1422 if (!reparse && (d == dest || (*s && isALNUM(*s) ))) {
a687059c
LW
1423 *d++ = *s++;
1424 continue;
1425 }
1426 else if (!reparse)
1427 reparse = s;
1428 switch (*s++) {
1429 /* { */
1430 case '}':
1431 brackets--;
1432 if (reparse && reparse == s - 1)
1433 reparse = Nullch;
1434 break;
1435 case '{': /* } */
1436 brackets++;
1437 break;
1438 }
1439 }
378cc40b
LW
1440 *d = '\0';
1441 d = dest;
378cc40b
LW
1442 }
1443 else
1444 d[1] = '\0';
1445 }
de3bb511
LW
1446 if (*d == '^' && (isUPPER(*s) || index("[\\]^_?", *s))) {
1447#ifdef DEBUGGING
1448 if (*s == 'D')
1449 debug |= 32768;
1450#endif
fe14fcc3 1451 *d = *s++ ^ 64;
de3bb511 1452 }
378cc40b
LW
1453 return s;
1454}
1455
de3bb511 1456void
d48672a2
LW
1457scanconst(spat,string,len)
1458SPAT *spat;
378cc40b 1459char *string;
a687059c 1460int len;
378cc40b 1461{
de3bb511 1462 register STR *tmpstr;
378cc40b
LW
1463 register char *t;
1464 register char *d;
a687059c 1465 register char *e;
d48672a2
LW
1466 char *origstring = string;
1467 static char *vert = "|";
378cc40b 1468
d48672a2 1469 if (ninstr(string, string+len, vert, vert+1))
de3bb511 1470 return;
d48672a2
LW
1471 if (*string == '^')
1472 string++, len--;
de3bb511
LW
1473 tmpstr = Str_new(86,len);
1474 str_nset(tmpstr,string,len);
1475 t = str_get(tmpstr);
a687059c 1476 e = t + len;
de3bb511 1477 tmpstr->str_u.str_useful = 100;
a687059c 1478 for (d=t; d < e; ) {
378cc40b 1479 switch (*d) {
a687059c 1480 case '{':
de3bb511 1481 if (isDIGIT(d[1]))
a687059c
LW
1482 e = d;
1483 else
1484 goto defchar;
1485 break;
1486 case '.': case '[': case '$': case '(': case ')': case '|': case '+':
de3bb511 1487 case '^':
a687059c 1488 e = d;
378cc40b
LW
1489 break;
1490 case '\\':
de3bb511 1491 if (d[1] && index("wWbB0123456789sSdDlLuUExc",d[1])) {
a687059c 1492 e = d;
378cc40b
LW
1493 break;
1494 }
a687059c
LW
1495 (void)bcopy(d+1,d,e-d);
1496 e--;
378cc40b
LW
1497 switch(*d) {
1498 case 'n':
1499 *d = '\n';
1500 break;
1501 case 't':
1502 *d = '\t';
1503 break;
1504 case 'f':
1505 *d = '\f';
1506 break;
1507 case 'r':
1508 *d = '\r';
1509 break;
fe14fcc3
LW
1510 case 'e':
1511 *d = '\033';
1512 break;
1513 case 'a':
1514 *d = '\007';
1515 break;
378cc40b
LW
1516 }
1517 /* FALL THROUGH */
1518 default:
a687059c
LW
1519 defchar:
1520 if (d[1] == '*' || (d[1] == '{' && d[2] == '0') || d[1] == '?') {
1521 e = d;
378cc40b
LW
1522 break;
1523 }
1524 d++;
1525 }
1526 }
a687059c 1527 if (d == t) {
de3bb511
LW
1528 str_free(tmpstr);
1529 return;
378cc40b 1530 }
a687059c 1531 *d = '\0';
de3bb511 1532 tmpstr->str_cur = d - t;
d48672a2
LW
1533 if (d == t+len)
1534 spat->spat_flags |= SPAT_ALL;
1535 if (*origstring != '^')
1536 spat->spat_flags |= SPAT_SCANFIRST;
de3bb511 1537 spat->spat_short = tmpstr;
d48672a2 1538 spat->spat_slen = d - t;
378cc40b
LW
1539}
1540
1541char *
1542scanpat(s)
1543register char *s;
1544{
a687059c 1545 register SPAT *spat;
378cc40b 1546 register char *d;
a687059c
LW
1547 register char *e;
1548 int len;
1549 SPAT savespat;
395c3793 1550 STR *str = Str_new(93,0);
1462b684 1551 char delim;
378cc40b 1552
a687059c
LW
1553 Newz(801,spat,1,SPAT);
1554 spat->spat_next = curstash->tbl_spatroot; /* link into spat list */
1555 curstash->tbl_spatroot = spat;
378cc40b
LW
1556
1557 switch (*s++) {
1558 case 'm':
1559 s++;
1560 break;
1561 case '/':
1562 break;
1563 case '?':
1564 spat->spat_flags |= SPAT_ONCE;
1565 break;
1566 default:
1567 fatal("panic: scanpat");
1568 }
395c3793 1569 s = str_append_till(str,s,bufend,s[-1],patleave);
a687059c 1570 if (s >= bufend) {
395c3793 1571 str_free(str);
a687059c
LW
1572 yyerror("Search pattern not terminated");
1573 yylval.arg = Nullarg;
1574 return s;
1575 }
1462b684 1576 delim = *s++;
d48672a2 1577 while (*s == 'i' || *s == 'o' || *s == 'g') {
a687059c
LW
1578 if (*s == 'i') {
1579 s++;
1580 sawi = TRUE;
1581 spat->spat_flags |= SPAT_FOLD;
1582 }
1583 if (*s == 'o') {
1584 s++;
1585 spat->spat_flags |= SPAT_KEEP;
1586 }
d48672a2
LW
1587 if (*s == 'g') {
1588 s++;
1589 spat->spat_flags |= SPAT_GLOBAL;
1590 }
378cc40b 1591 }
395c3793
LW
1592 len = str->str_cur;
1593 e = str->str_ptr + len;
1462b684
LW
1594 if (delim == '\'')
1595 d = e;
1596 else
1597 d = str->str_ptr;
1598 for (; d < e; d++) {
e929a76b
LW
1599 if (*d == '\\')
1600 d++;
1601 else if ((*d == '$' && d[1] && d[1] != '|' && d[1] != ')') ||
1602 (*d == '@')) {
378cc40b
LW
1603 register ARG *arg;
1604
1605 spat->spat_runtime = arg = op_new(1);
1606 arg->arg_type = O_ITEM;
1607 arg[1].arg_type = A_DOUBLE;
395c3793 1608 arg[1].arg_ptr.arg_str = str_smake(str);
fe14fcc3 1609 d = scanident(d,bufend,buf);
a687059c
LW
1610 (void)stabent(buf,TRUE); /* make sure it's created */
1611 for (; d < e; d++) {
e929a76b
LW
1612 if (*d == '\\')
1613 d++;
1614 else if (*d == '$' && d[1] && d[1] != '|' && d[1] != ')') {
fe14fcc3 1615 d = scanident(d,bufend,buf);
a687059c
LW
1616 (void)stabent(buf,TRUE);
1617 }
e929a76b 1618 else if (*d == '@') {
fe14fcc3 1619 d = scanident(d,bufend,buf);
a687059c
LW
1620 if (strEQ(buf,"ARGV") || strEQ(buf,"ENV") ||
1621 strEQ(buf,"SIG") || strEQ(buf,"INC"))
1622 (void)stabent(buf,TRUE);
1623 }
1624 }
378cc40b
LW
1625 goto got_pat; /* skip compiling for now */
1626 }
1627 }
a687059c
LW
1628 if (spat->spat_flags & SPAT_FOLD)
1629#ifdef STRUCTCOPY
1630 savespat = *spat;
1631#else
1632 (void)bcopy((char *)spat, (char *)&savespat, sizeof(SPAT));
1633#endif
d48672a2 1634 scanconst(spat,str->str_ptr,len);
a687059c
LW
1635 if ((spat->spat_flags & SPAT_ALL) && (spat->spat_flags & SPAT_SCANFIRST)) {
1636 fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD);
395c3793 1637 spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len,
e929a76b 1638 spat->spat_flags & SPAT_FOLD);
a687059c
LW
1639 /* Note that this regexp can still be used if someone says
1640 * something like /a/ && s//b/; so we can't delete it.
1641 */
1642 }
1643 else {
1644 if (spat->spat_flags & SPAT_FOLD)
1645#ifdef STRUCTCOPY
1646 *spat = savespat;
1647#else
1648 (void)bcopy((char *)&savespat, (char *)spat, sizeof(SPAT));
1649#endif
1650 if (spat->spat_short)
1651 fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD);
395c3793 1652 spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len,
fe14fcc3 1653 spat->spat_flags & SPAT_FOLD);
a687059c
LW
1654 hoistmust(spat);
1655 }
378cc40b 1656 got_pat:
395c3793 1657 str_free(str);
378cc40b
LW
1658 yylval.arg = make_match(O_MATCH,stab2arg(A_STAB,defstab),spat);
1659 return s;
1660}
1661
1662char *
1663scansubst(s)
1664register char *s;
1665{
a687059c 1666 register SPAT *spat;
378cc40b 1667 register char *d;
a687059c
LW
1668 register char *e;
1669 int len;
395c3793 1670 STR *str = Str_new(93,0);
378cc40b 1671
a687059c
LW
1672 Newz(802,spat,1,SPAT);
1673 spat->spat_next = curstash->tbl_spatroot; /* link into spat list */
1674 curstash->tbl_spatroot = spat;
378cc40b 1675
395c3793 1676 s = str_append_till(str,s+1,bufend,*s,patleave);
a687059c 1677 if (s >= bufend) {
395c3793 1678 str_free(str);
a687059c
LW
1679 yyerror("Substitution pattern not terminated");
1680 yylval.arg = Nullarg;
1681 return s;
1682 }
395c3793
LW
1683 len = str->str_cur;
1684 e = str->str_ptr + len;
1685 for (d = str->str_ptr; d < e; d++) {
1686 if (*d == '\\')
1687 d++;
1688 else if ((*d == '$' && d[1] && d[1] != '|' && /*(*/ d[1] != ')') ||
1689 *d == '@' ) {
378cc40b
LW
1690 register ARG *arg;
1691
1692 spat->spat_runtime = arg = op_new(1);
1693 arg->arg_type = O_ITEM;
1694 arg[1].arg_type = A_DOUBLE;
395c3793 1695 arg[1].arg_ptr.arg_str = str_smake(str);
de3bb511 1696 d = scanident(d,e,buf);
a687059c
LW
1697 (void)stabent(buf,TRUE); /* make sure it's created */
1698 for (; *d; d++) {
1699 if (*d == '$' && d[1] && d[-1] != '\\' && d[1] != '|') {
de3bb511 1700 d = scanident(d,e,buf);
a687059c
LW
1701 (void)stabent(buf,TRUE);
1702 }
1703 else if (*d == '@' && d[-1] != '\\') {
de3bb511 1704 d = scanident(d,e,buf);
a687059c
LW
1705 if (strEQ(buf,"ARGV") || strEQ(buf,"ENV") ||
1706 strEQ(buf,"SIG") || strEQ(buf,"INC"))
1707 (void)stabent(buf,TRUE);
1708 }
1709 }
378cc40b
LW
1710 goto get_repl; /* skip compiling for now */
1711 }
1712 }
d48672a2 1713 scanconst(spat,str->str_ptr,len);
378cc40b
LW
1714get_repl:
1715 s = scanstr(s);
a687059c 1716 if (s >= bufend) {
395c3793 1717 str_free(str);
a687059c
LW
1718 yyerror("Substitution replacement not terminated");
1719 yylval.arg = Nullarg;
1720 return s;
1721 }
378cc40b 1722 spat->spat_repl = yylval.arg;
a687059c
LW
1723 if ((spat->spat_repl[1].arg_type & A_MASK) == A_SINGLE)
1724 spat->spat_flags |= SPAT_CONST;
1725 else if ((spat->spat_repl[1].arg_type & A_MASK) == A_DOUBLE) {
1726 STR *tmpstr;
1727 register char *t;
1728
1729 spat->spat_flags |= SPAT_CONST;
1730 tmpstr = spat->spat_repl[1].arg_ptr.arg_str;
1731 e = tmpstr->str_ptr + tmpstr->str_cur;
1732 for (t = tmpstr->str_ptr; t < e; t++) {
9f68db38 1733 if (*t == '$' && t[1] && (index("`'&+0123456789",t[1]) ||
de3bb511 1734 (t[1] == '{' /*}*/ && isDIGIT(t[2])) ))
a687059c
LW
1735 spat->spat_flags &= ~SPAT_CONST;
1736 }
1737 }
1738 while (*s == 'g' || *s == 'i' || *s == 'e' || *s == 'o') {
1739 if (*s == 'e') {
1740 s++;
1741 if ((spat->spat_repl[1].arg_type & A_MASK) == A_DOUBLE)
1742 spat->spat_repl[1].arg_type = A_SINGLE;
de3bb511
LW
1743 spat->spat_repl = make_op(
1744 (spat->spat_repl[1].arg_type == A_SINGLE ? O_EVALONCE : O_EVAL),
1745 2,
a687059c
LW
1746 spat->spat_repl,
1747 Nullarg,
395c3793 1748 Nullarg);
a687059c
LW
1749 spat->spat_flags &= ~SPAT_CONST;
1750 }
378cc40b
LW
1751 if (*s == 'g') {
1752 s++;
d48672a2 1753 spat->spat_flags |= SPAT_GLOBAL;
378cc40b
LW
1754 }
1755 if (*s == 'i') {
1756 s++;
a687059c 1757 sawi = TRUE;
378cc40b 1758 spat->spat_flags |= SPAT_FOLD;
a687059c
LW
1759 if (!(spat->spat_flags & SPAT_SCANFIRST)) {
1760 str_free(spat->spat_short); /* anchored opt doesn't do */
1761 spat->spat_short = Nullstr; /* case insensitive match */
1762 spat->spat_slen = 0;
1763 }
1764 }
1765 if (*s == 'o') {
1766 s++;
1767 spat->spat_flags |= SPAT_KEEP;
378cc40b
LW
1768 }
1769 }
a687059c
LW
1770 if (spat->spat_short && (spat->spat_flags & SPAT_SCANFIRST))
1771 fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD);
378cc40b 1772 if (!spat->spat_runtime) {
395c3793 1773 spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len,
fe14fcc3 1774 spat->spat_flags & SPAT_FOLD);
378cc40b 1775 hoistmust(spat);
378cc40b
LW
1776 }
1777 yylval.arg = make_match(O_SUBST,stab2arg(A_STAB,defstab),spat);
395c3793 1778 str_free(str);
378cc40b
LW
1779 return s;
1780}
1781
1462b684 1782void
378cc40b
LW
1783hoistmust(spat)
1784register SPAT *spat;
1785{
d48672a2
LW
1786 if (!spat->spat_short && spat->spat_regexp->regstart &&
1787 (!spat->spat_regexp->regmust || spat->spat_regexp->reganch & ROPT_ANCH)
1788 ) {
d48672a2
LW
1789 if (!(spat->spat_regexp->reganch & ROPT_ANCH))
1790 spat->spat_flags |= SPAT_SCANFIRST;
1462b684
LW
1791 else if (spat->spat_flags & SPAT_FOLD)
1792 return;
1793 spat->spat_short = str_smake(spat->spat_regexp->regstart);
d48672a2
LW
1794 }
1795 else if (spat->spat_regexp->regmust) {/* is there a better short-circuit? */
378cc40b 1796 if (spat->spat_short &&
a687059c
LW
1797 str_eq(spat->spat_short,spat->spat_regexp->regmust))
1798 {
378cc40b
LW
1799 if (spat->spat_flags & SPAT_SCANFIRST) {
1800 str_free(spat->spat_short);
1801 spat->spat_short = Nullstr;
1802 }
1803 else {
1804 str_free(spat->spat_regexp->regmust);
1805 spat->spat_regexp->regmust = Nullstr;
1806 return;
1807 }
1808 }
1809 if (!spat->spat_short || /* promote the better string */
1810 ((spat->spat_flags & SPAT_SCANFIRST) &&
1811 (spat->spat_short->str_cur < spat->spat_regexp->regmust->str_cur) )){
1812 str_free(spat->spat_short); /* ok if null */
1813 spat->spat_short = spat->spat_regexp->regmust;
1814 spat->spat_regexp->regmust = Nullstr;
1815 spat->spat_flags |= SPAT_SCANFIRST;
1816 }
1817 }
1818}
1819
1820char *
a687059c 1821expand_charset(s,len,retlen)
378cc40b 1822register char *s;
a687059c
LW
1823int len;
1824int *retlen;
378cc40b 1825{
e929a76b 1826 char t[520];
378cc40b
LW
1827 register char *d = t;
1828 register int i;
a687059c 1829 register char *send = s + len;
378cc40b 1830
e929a76b 1831 while (s < send && d - t <= 256) {
a687059c 1832 if (s[1] == '-' && s+2 < send) {
fe14fcc3 1833 for (i = (s[0] & 0377); i <= (s[2] & 0377); i++)
378cc40b
LW
1834 *d++ = i;
1835 s += 3;
1836 }
1837 else
1838 *d++ = *s++;
1839 }
1840 *d = '\0';
a687059c
LW
1841 *retlen = d - t;
1842 return nsavestr(t,d-t);
378cc40b
LW
1843}
1844
1845char *
1846scantrans(s)
1847register char *s;
1848{
1849 ARG *arg =
a687059c 1850 l(make_op(O_TRANS,2,stab2arg(A_STAB,defstab),Nullarg,Nullarg));
378cc40b
LW
1851 register char *t;
1852 register char *r;
395c3793 1853 register short *tbl;
378cc40b 1854 register int i;
13281fa4 1855 register int j;
a687059c 1856 int tlen, rlen;
395c3793
LW
1857 int squash;
1858 int delete;
1859 int complement;
378cc40b 1860
395c3793 1861 New(803,tbl,256,short);
378cc40b 1862 arg[2].arg_type = A_NULL;
395c3793 1863 arg[2].arg_ptr.arg_cval = (char*) tbl;
378cc40b 1864 s = scanstr(s);
a687059c
LW
1865 if (s >= bufend) {
1866 yyerror("Translation pattern not terminated");
1867 yylval.arg = Nullarg;
1868 return s;
1869 }
1870 t = expand_charset(yylval.arg[1].arg_ptr.arg_str->str_ptr,
1871 yylval.arg[1].arg_ptr.arg_str->str_cur,&tlen);
fe14fcc3 1872 arg_free(yylval.arg);
378cc40b 1873 s = scanstr(s-1);
a687059c
LW
1874 if (s >= bufend) {
1875 yyerror("Translation replacement not terminated");
1876 yylval.arg = Nullarg;
1877 return s;
1878 }
395c3793
LW
1879 complement = delete = squash = 0;
1880 while (*s == 'c' || *s == 'd' || *s == 's') {
1881 if (*s == 'c')
1882 complement = 1;
1883 else if (*s == 'd')
1884 delete = 2;
1885 else
1886 squash = 1;
1887 s++;
1888 }
a687059c
LW
1889 r = expand_charset(yylval.arg[1].arg_ptr.arg_str->str_ptr,
1890 yylval.arg[1].arg_ptr.arg_str->str_cur,&rlen);
fe14fcc3 1891 arg_free(yylval.arg);
395c3793 1892 arg[2].arg_len = delete|squash;
378cc40b 1893 yylval.arg = arg;
395c3793 1894 if (!rlen && !delete) {
a687059c 1895 Safefree(r);
ffed7fef 1896 r = t; rlen = tlen;
378cc40b 1897 }
395c3793
LW
1898 if (complement) {
1899 Zero(tbl, 256, short);
1900 for (i = 0; i < tlen; i++)
1901 tbl[t[i] & 0377] = -1;
fe14fcc3 1902 for (i = 0, j = 0; i < 256; i++) {
395c3793
LW
1903 if (!tbl[i]) {
1904 if (j >= rlen) {
fe14fcc3 1905 if (delete)
395c3793 1906 tbl[i] = -2;
fe14fcc3
LW
1907 else
1908 tbl[i] = r[j-1];
395c3793 1909 }
fe14fcc3
LW
1910 else
1911 tbl[i] = r[j++];
395c3793
LW
1912 }
1913 }
1914 }
1915 else {
1916 for (i = 0; i < 256; i++)
1917 tbl[i] = -1;
1918 for (i = 0, j = 0; i < tlen; i++,j++) {
1919 if (j >= rlen) {
1920 if (delete) {
1921 if (tbl[t[i] & 0377] == -1)
1922 tbl[t[i] & 0377] = -2;
1923 continue;
1924 }
1925 --j;
1926 }
1927 if (tbl[t[i] & 0377] == -1)
34de22dd 1928 tbl[t[i] & 0377] = r[j] & 0377;
395c3793 1929 }
378cc40b
LW
1930 }
1931 if (r != t)
a687059c
LW
1932 Safefree(r);
1933 Safefree(t);
378cc40b
LW
1934 return s;
1935}
1936
1937char *
1938scanstr(s)
1939register char *s;
1940{
1941 register char term;
1942 register char *d;
1943 register ARG *arg;
a687059c 1944 register char *send;
378cc40b
LW
1945 register bool makesingle = FALSE;
1946 register STAB *stab;
a687059c
LW
1947 bool alwaysdollar = FALSE;
1948 bool hereis = FALSE;
1949 STR *herewas;
e929a76b 1950 STR *str;
fe14fcc3 1951 char *leave = "\\$@nrtfbeacx0123456789[{]}lLuUE"; /* which backslash sequences to keep */
a687059c 1952 int len;
378cc40b
LW
1953
1954 arg = op_new(1);
1955 yylval.arg = arg;
1956 arg->arg_type = O_ITEM;
1957
1958 switch (*s) {
1959 default: /* a substitution replacement */
1960 arg[1].arg_type = A_DOUBLE;
1961 makesingle = TRUE; /* maybe disable runtime scanning */
1962 term = *s;
1963 if (term == '\'')
1964 leave = Nullch;
1965 goto snarf_it;
1966 case '0':
1967 {
395c3793 1968 unsigned long i;
378cc40b
LW
1969 int shift;
1970
1971 arg[1].arg_type = A_SINGLE;
1972 if (s[1] == 'x') {
1973 shift = 4;
1974 s += 2;
1975 }
1976 else if (s[1] == '.')
1977 goto decimal;
1978 else
1979 shift = 3;
1980 i = 0;
1981 for (;;) {
1982 switch (*s) {
1983 default:
1984 goto out;
de3bb511
LW
1985 case '_':
1986 s++;
1987 break;
378cc40b
LW
1988 case '8': case '9':
1989 if (shift != 4)
a687059c 1990 yyerror("Illegal octal digit");
378cc40b
LW
1991 /* FALL THROUGH */
1992 case '0': case '1': case '2': case '3': case '4':
1993 case '5': case '6': case '7':
1994 i <<= shift;
1995 i += *s++ & 15;
1996 break;
1997 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
1998 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
1999 if (shift != 4)
2000 goto out;
2001 i <<= 4;
2002 i += (*s++ & 7) + 9;
2003 break;
2004 }
2005 }
2006 out:
e929a76b
LW
2007 str = Str_new(92,0);
2008 str_numset(str,(double)i);
2009 if (str->str_ptr) {
2010 Safefree(str->str_ptr);
2011 str->str_ptr = Nullch;
2012 str->str_len = str->str_cur = 0;
2013 }
2014 arg[1].arg_ptr.arg_str = str;
378cc40b
LW
2015 }
2016 break;
2017 case '1': case '2': case '3': case '4': case '5':
2018 case '6': case '7': case '8': case '9': case '.':
2019 decimal:
2020 arg[1].arg_type = A_SINGLE;
2021 d = tokenbuf;
de3bb511 2022 while (isDIGIT(*s) || *s == '_') {
378cc40b
LW
2023 if (*s == '_')
2024 s++;
2025 else
2026 *d++ = *s++;
2027 }
a687059c 2028 if (*s == '.' && s[1] && index("0123456789eE ;",s[1])) {
378cc40b 2029 *d++ = *s++;
de3bb511 2030 while (isDIGIT(*s) || *s == '_') {
378cc40b
LW
2031 if (*s == '_')
2032 s++;
2033 else
2034 *d++ = *s++;
2035 }
2036 }
a687059c 2037 if (*s && index("eE",*s) && index("+-0123456789",s[1])) {
378cc40b
LW
2038 *d++ = *s++;
2039 if (*s == '+' || *s == '-')
2040 *d++ = *s++;
de3bb511 2041 while (isDIGIT(*s))
378cc40b
LW
2042 *d++ = *s++;
2043 }
2044 *d = '\0';
e929a76b
LW
2045 str = Str_new(92,0);
2046 str_numset(str,atof(tokenbuf));
2047 if (str->str_ptr) {
2048 Safefree(str->str_ptr);
2049 str->str_ptr = Nullch;
2050 str->str_len = str->str_cur = 0;
2051 }
2052 arg[1].arg_ptr.arg_str = str;
378cc40b 2053 break;
378cc40b 2054 case '<':
a687059c
LW
2055 if (*++s == '<') {
2056 hereis = TRUE;
2057 d = tokenbuf;
2058 if (!rsfp)
2059 *d++ = '\n';
2060 if (*++s && index("`'\"",*s)) {
2061 term = *s++;
2062 s = cpytill(d,s,bufend,term,&len);
2063 if (s < bufend)
2064 s++;
2065 d += len;
2066 }
2067 else {
2068 if (*s == '\\')
2069 s++, term = '\'';
2070 else
2071 term = '"';
de3bb511 2072 while (isALNUM(*s))
a687059c
LW
2073 *d++ = *s++;
2074 } /* assuming tokenbuf won't clobber */
2075 *d++ = '\n';
2076 *d = '\0';
2077 len = d - tokenbuf;
2078 d = "\n";
2079 if (rsfp || !(d=ninstr(s,bufend,d,d+1)))
2080 herewas = str_make(s,bufend-s);
2081 else
2082 s--, herewas = str_make(s,d-s);
2083 s += herewas->str_cur;
2084 if (term == '\'')
2085 goto do_single;
2086 if (term == '`')
2087 goto do_back;
2088 goto do_double;
2089 }
378cc40b 2090 d = tokenbuf;
a687059c
LW
2091 s = cpytill(d,s,bufend,'>',&len);
2092 if (s < bufend)
378cc40b
LW
2093 s++;
2094 if (*d == '$') d++;
de3bb511 2095 while (*d && (isALNUM(*d) || *d == '\''))
a687059c
LW
2096 d++;
2097 if (d - tokenbuf != len) {
378cc40b
LW
2098 d = tokenbuf;
2099 arg[1].arg_type = A_GLOB;
a687059c 2100 d = nsavestr(d,len);
378cc40b 2101 arg[1].arg_ptr.arg_stab = stab = genstab();
a687059c
LW
2102 stab_io(stab) = stio_new();
2103 stab_val(stab) = str_make(d,len);
a687059c
LW
2104 Safefree(d);
2105 set_csh();
378cc40b
LW
2106 }
2107 else {
2108 d = tokenbuf;
a687059c
LW
2109 if (!len)
2110 (void)strcpy(d,"ARGV");
378cc40b
LW
2111 if (*d == '$') {
2112 arg[1].arg_type = A_INDREAD;
2113 arg[1].arg_ptr.arg_stab = stabent(d+1,TRUE);
2114 }
2115 else {
2116 arg[1].arg_type = A_READ;
378cc40b 2117 arg[1].arg_ptr.arg_stab = stabent(d,TRUE);
a687059c
LW
2118 if (!stab_io(arg[1].arg_ptr.arg_stab))
2119 stab_io(arg[1].arg_ptr.arg_stab) = stio_new();
378cc40b 2120 if (strEQ(d,"ARGV")) {
a687059c
LW
2121 (void)aadd(arg[1].arg_ptr.arg_stab);
2122 stab_io(arg[1].arg_ptr.arg_stab)->flags |=
378cc40b
LW
2123 IOF_ARGV|IOF_START;
2124 }
2125 }
2126 }
2127 break;
a687059c
LW
2128
2129 case 'q':
2130 s++;
2131 if (*s == 'q') {
2132 s++;
2133 goto do_double;
2134 }
fe14fcc3
LW
2135 if (*s == 'x') {
2136 s++;
2137 goto do_back;
2138 }
a687059c
LW
2139 /* FALL THROUGH */
2140 case '\'':
2141 do_single:
2142 term = *s;
2143 arg[1].arg_type = A_SINGLE;
2144 leave = Nullch;
2145 goto snarf_it;
2146
378cc40b 2147 case '"':
a687059c
LW
2148 do_double:
2149 term = *s;
378cc40b
LW
2150 arg[1].arg_type = A_DOUBLE;
2151 makesingle = TRUE; /* maybe disable runtime scanning */
a687059c 2152 alwaysdollar = TRUE; /* treat $) and $| as variables */
378cc40b
LW
2153 goto snarf_it;
2154 case '`':
a687059c 2155 do_back:
378cc40b 2156 term = *s;
a687059c
LW
2157 arg[1].arg_type = A_BACKTICK;
2158 set_csh();
2159 alwaysdollar = TRUE; /* treat $) and $| as variables */
378cc40b
LW
2160 snarf_it:
2161 {
2162 STR *tmpstr;
378cc40b
LW
2163 char *tmps;
2164
d48672a2 2165 CLINE;
e929a76b 2166 multi_start = curcmd->c_line;
a687059c
LW
2167 if (hereis)
2168 multi_open = multi_close = '<';
2169 else {
2170 multi_open = term;
395c3793 2171 if (term && (tmps = index("([{< )]}> )]}>",term)))
a687059c
LW
2172 term = tmps[5];
2173 multi_close = term;
2174 }
9f68db38 2175 tmpstr = Str_new(87,80);
a687059c
LW
2176 if (hereis) {
2177 term = *tokenbuf;
2178 if (!rsfp) {
2179 d = s;
2180 while (s < bufend &&
2181 (*s != term || bcmp(s,tokenbuf,len) != 0) ) {
2182 if (*s++ == '\n')
e929a76b 2183 curcmd->c_line++;
a687059c
LW
2184 }
2185 if (s >= bufend) {
e929a76b 2186 curcmd->c_line = multi_start;
a687059c
LW
2187 fatal("EOF in string");
2188 }
2189 str_nset(tmpstr,d+1,s-d);
2190 s += len - 1;
2191 str_ncat(herewas,s,bufend-s);
2192 str_replace(linestr,herewas);
2193 oldoldbufptr = oldbufptr = bufptr = s = str_get(linestr);
2194 bufend = linestr->str_ptr + linestr->str_cur;
2195 hereis = FALSE;
2196 }
e929a76b
LW
2197 else
2198 str_nset(tmpstr,"",0); /* avoid "uninitialized" warning */
a687059c
LW
2199 }
2200 else
2201 s = str_append_till(tmpstr,s+1,bufend,term,leave);
2202 while (s >= bufend) { /* multiple line string? */
2203 if (!rsfp ||
2204 !(oldoldbufptr = oldbufptr = s = str_gets(linestr, rsfp, 0))) {
e929a76b 2205 curcmd->c_line = multi_start;
378cc40b
LW
2206 fatal("EOF in string");
2207 }
e929a76b 2208 curcmd->c_line++;
a687059c
LW
2209 if (perldb) {
2210 STR *str = Str_new(88,0);
2211
2212 str_sset(str,linestr);
395c3793
LW
2213 astore(stab_xarray(curcmd->c_filestab),
2214 (int)curcmd->c_line,str);
a687059c
LW
2215 }
2216 bufend = linestr->str_ptr + linestr->str_cur;
2217 if (hereis) {
2218 if (*s == term && bcmp(s,tokenbuf,len) == 0) {
2219 s = bufend - 1;
2220 *s = ' ';
2221 str_scat(linestr,herewas);
2222 bufend = linestr->str_ptr + linestr->str_cur;
2223 }
2224 else {
2225 s = bufend;
2226 str_scat(tmpstr,linestr);
2227 }
2228 }
2229 else
2230 s = str_append_till(tmpstr,s,bufend,term,leave);
378cc40b 2231 }
e929a76b 2232 multi_end = curcmd->c_line;
378cc40b 2233 s++;
a687059c
LW
2234 if (tmpstr->str_cur + 5 < tmpstr->str_len) {
2235 tmpstr->str_len = tmpstr->str_cur + 1;
2236 Renew(tmpstr->str_ptr, tmpstr->str_len, char);
2237 }
2238 if ((arg[1].arg_type & A_MASK) == A_SINGLE) {
378cc40b
LW
2239 arg[1].arg_ptr.arg_str = tmpstr;
2240 break;
2241 }
2242 tmps = s;
2243 s = tmpstr->str_ptr;
a687059c
LW
2244 send = s + tmpstr->str_cur;
2245 while (s < send) { /* see if we can make SINGLE */
de3bb511 2246 if (*s == '\\' && s[1] && isDIGIT(s[1]) && !isDIGIT(s[2]) &&
e929a76b 2247 !alwaysdollar && s[1] != '0')
378cc40b 2248 *s = '$'; /* grandfather \digit in subst */
a687059c
LW
2249 if ((*s == '$' || *s == '@') && s+1 < send &&
2250 (alwaysdollar || (s[1] != ')' && s[1] != '|'))) {
378cc40b
LW
2251 makesingle = FALSE; /* force interpretation */
2252 }
a687059c 2253 else if (*s == '\\' && s+1 < send) {
fe14fcc3
LW
2254 if (index("lLuUE",s[1]))
2255 makesingle = FALSE;
378cc40b
LW
2256 s++;
2257 }
2258 s++;
2259 }
2260 s = d = tmpstr->str_ptr; /* assuming shrinkage only */
a687059c
LW
2261 while (s < send) {
2262 if ((*s == '$' && s+1 < send &&
2263 (alwaysdollar || /*(*/ (s[1] != ')' && s[1] != '|')) ) ||
2264 (*s == '@' && s+1 < send) ) {
de3bb511
LW
2265 if (s[1] == '#' && (isALPHA(s[2]) || s[2] == '_'))
2266 *d++ = *s++;
fe14fcc3 2267 len = scanident(s,send,tokenbuf) - s;
a687059c
LW
2268 if (*s == '$' || strEQ(tokenbuf,"ARGV")
2269 || strEQ(tokenbuf,"ENV")
2270 || strEQ(tokenbuf,"SIG")
2271 || strEQ(tokenbuf,"INC") )
2272 (void)stabent(tokenbuf,TRUE); /* make sure it exists */
378cc40b
LW
2273 while (len--)
2274 *d++ = *s++;
2275 continue;
2276 }
a687059c 2277 else if (*s == '\\' && s+1 < send) {
378cc40b
LW
2278 s++;
2279 switch (*s) {
2280 default:
a687059c 2281 if (!makesingle && (!leave || (*s && index(leave,*s))))
378cc40b
LW
2282 *d++ = '\\';
2283 *d++ = *s++;
2284 continue;
2285 case '0': case '1': case '2': case '3':
2286 case '4': case '5': case '6': case '7':
fe14fcc3
LW
2287 *d++ = scanoct(s, 3, &len);
2288 s += len;
2289 continue;
2290 case 'x':
2291 *d++ = scanhex(++s, 2, &len);
2292 s += len;
2293 continue;
2294 case 'c':
2295 s++;
2296 *d = *s++;
de3bb511 2297 if (isLOWER(*d))
fe14fcc3
LW
2298 *d = toupper(*d);
2299 *d++ ^= 64;
378cc40b
LW
2300 continue;
2301 case 'b':
2302 *d++ = '\b';
2303 break;
2304 case 'n':
2305 *d++ = '\n';
2306 break;
2307 case 'r':
2308 *d++ = '\r';
2309 break;
2310 case 'f':
2311 *d++ = '\f';
2312 break;
2313 case 't':
2314 *d++ = '\t';
2315 break;
fe14fcc3
LW
2316 case 'e':
2317 *d++ = '\033';
2318 break;
2319 case 'a':
2320 *d++ = '\007';
2321 break;
378cc40b
LW
2322 }
2323 s++;
2324 continue;
2325 }
2326 *d++ = *s++;
2327 }
2328 *d = '\0';
2329
a687059c
LW
2330 if ((arg[1].arg_type & A_MASK) == A_DOUBLE && makesingle)
2331 arg[1].arg_type = A_SINGLE; /* now we can optimize on it */
2332
a687059c 2333 tmpstr->str_cur = d - tmpstr->str_ptr;
378cc40b
LW
2334 arg[1].arg_ptr.arg_str = tmpstr;
2335 s = tmps;
2336 break;
2337 }
2338 }
a687059c
LW
2339 if (hereis)
2340 str_free(herewas);
378cc40b
LW
2341 return s;
2342}
2343
2344FCMD *
2345load_format()
2346{
2347 FCMD froot;
2348 FCMD *flinebeg;
0f85fab0 2349 char *eol;
378cc40b
LW
2350 register FCMD *fprev = &froot;
2351 register FCMD *fcmd;
2352 register char *s;
2353 register char *t;
a687059c 2354 register STR *str;
378cc40b 2355 bool noblank;
a687059c 2356 bool repeater;
378cc40b 2357
a687059c 2358 Zero(&froot, 1, FCMD);
0f85fab0 2359 s = bufptr;
27e2fb84 2360 while (s < bufend || (rsfp && (s = str_gets(linestr,rsfp, 0)) != Nullch)) {
e929a76b 2361 curcmd->c_line++;
0f85fab0
LW
2362 if (in_eval && !rsfp) {
2363 eol = index(s,'\n');
2364 if (!eol++)
2365 eol = bufend;
2366 }
2367 else
2368 eol = bufend = linestr->str_ptr + linestr->str_cur;
395c3793
LW
2369 if (perldb) {
2370 STR *tmpstr = Str_new(89,0);
2371
2372 str_nset(tmpstr, s, eol-s);
2373 astore(stab_xarray(curcmd->c_filestab), (int)curcmd->c_line,tmpstr);
2374 }
27e2fb84 2375 if (*s == '.') {
de3bb511 2376 /*SUPPRESS 530*/
27e2fb84
LW
2377 for (t = s+1; *t == ' ' || *t == '\t'; t++) ;
2378 if (*t == '\n') {
2379 bufptr = s;
2380 return froot.f_next;
2381 }
378cc40b 2382 }
0f85fab0
LW
2383 if (*s == '#') {
2384 s = eol;
378cc40b 2385 continue;
0f85fab0 2386 }
378cc40b
LW
2387 flinebeg = Nullfcmd;
2388 noblank = FALSE;
a687059c 2389 repeater = FALSE;
0f85fab0 2390 while (s < eol) {
a687059c 2391 Newz(804,fcmd,1,FCMD);
378cc40b
LW
2392 fprev->f_next = fcmd;
2393 fprev = fcmd;
0f85fab0 2394 for (t=s; t < eol && *t != '@' && *t != '^'; t++) {
378cc40b
LW
2395 if (*t == '~') {
2396 noblank = TRUE;
2397 *t = ' ';
a687059c
LW
2398 if (t[1] == '~') {
2399 repeater = TRUE;
2400 t[1] = ' ';
2401 }
378cc40b
LW
2402 }
2403 }
a687059c
LW
2404 fcmd->f_pre = nsavestr(s, t-s);
2405 fcmd->f_presize = t-s;
378cc40b 2406 s = t;
0f85fab0 2407 if (s >= eol) {
378cc40b
LW
2408 if (noblank)
2409 fcmd->f_flags |= FC_NOBLANK;
a687059c
LW
2410 if (repeater)
2411 fcmd->f_flags |= FC_REPEAT;
378cc40b
LW
2412 break;
2413 }
2414 if (!flinebeg)
2415 flinebeg = fcmd; /* start values here */
2416 if (*s++ == '^')
2417 fcmd->f_flags |= FC_CHOP; /* for doing text filling */
2418 switch (*s) {
2419 case '*':
2420 fcmd->f_type = F_LINES;
2421 *s = '\0';
2422 break;
2423 case '<':
2424 fcmd->f_type = F_LEFT;
2425 while (*s == '<')
2426 s++;
2427 break;
2428 case '>':
2429 fcmd->f_type = F_RIGHT;
2430 while (*s == '>')
2431 s++;
2432 break;
2433 case '|':
2434 fcmd->f_type = F_CENTER;
2435 while (*s == '|')
2436 s++;
2437 break;
395c3793
LW
2438 case '#':
2439 case '.':
2440 /* Catch the special case @... and handle it as a string
2441 field. */
2442 if (*s == '.' && s[1] == '.') {
2443 goto default_format;
2444 }
2445 fcmd->f_type = F_DECIMAL;
2446 {
2447 char *p;
2448
2449 /* Read a format in the form @####.####, where either group
2450 of ### may be empty, or the final .### may be missing. */
2451 while (*s == '#')
2452 s++;
2453 if (*s == '.') {
2454 s++;
2455 p = s;
2456 while (*s == '#')
2457 s++;
2458 fcmd->f_decimals = s-p;
2459 fcmd->f_flags |= FC_DP;
2460 } else {
2461 fcmd->f_decimals = 0;
2462 }
2463 }
2464 break;
378cc40b 2465 default:
395c3793 2466 default_format:
378cc40b
LW
2467 fcmd->f_type = F_LEFT;
2468 break;
2469 }
2470 if (fcmd->f_flags & FC_CHOP && *s == '.') {
2471 fcmd->f_flags |= FC_MORE;
2472 while (*s == '.')
2473 s++;
2474 }
2475 fcmd->f_size = s-t;
2476 }
2477 if (flinebeg) {
2478 again:
27e2fb84
LW
2479 if (s >= bufend &&
2480 (!rsfp || (s = str_gets(linestr, rsfp, 0)) == Nullch) )
378cc40b 2481 goto badform;
e929a76b 2482 curcmd->c_line++;
0f85fab0
LW
2483 if (in_eval && !rsfp) {
2484 eol = index(s,'\n');
2485 if (!eol++)
2486 eol = bufend;
2487 }
2488 else
2489 eol = bufend = linestr->str_ptr + linestr->str_cur;
395c3793
LW
2490 if (perldb) {
2491 STR *tmpstr = Str_new(90,0);
2492
2493 str_nset(tmpstr, s, eol-s);
2494 astore(stab_xarray(curcmd->c_filestab),
2495 (int)curcmd->c_line,tmpstr);
2496 }
0f85fab0 2497 if (strnEQ(s,".\n",2)) {
a687059c 2498 bufptr = s;
378cc40b
LW
2499 yyerror("Missing values line");
2500 return froot.f_next;
2501 }
0f85fab0
LW
2502 if (*s == '#') {
2503 s = eol;
378cc40b 2504 goto again;
0f85fab0
LW
2505 }
2506 str = flinebeg->f_unparsed = Str_new(91,eol - s);
a687059c
LW
2507 str->str_u.str_hash = curstash;
2508 str_nset(str,"(",1);
e929a76b 2509 flinebeg->f_line = curcmd->c_line;
0f85fab0
LW
2510 eol[-1] = '\0';
2511 if (!flinebeg->f_next->f_type || index(s, ',')) {
2512 eol[-1] = '\n';
2513 str_ncat(str, s, eol - s - 1);
a687059c 2514 str_ncat(str,",$$);",5);
0f85fab0 2515 s = eol;
a687059c
LW
2516 }
2517 else {
0f85fab0 2518 eol[-1] = '\n';
de3bb511 2519 while (s < eol && isSPACE(*s))
a687059c
LW
2520 s++;
2521 t = s;
0f85fab0 2522 while (s < eol) {
a687059c
LW
2523 switch (*s) {
2524 case ' ': case '\t': case '\n': case ';':
2525 str_ncat(str, t, s - t);
2526 str_ncat(str, "," ,1);
de3bb511 2527 while (s < eol && (isSPACE(*s) || *s == ';'))
a687059c
LW
2528 s++;
2529 t = s;
2530 break;
2531 case '$':
2532 str_ncat(str, t, s - t);
2533 t = s;
fe14fcc3 2534 s = scanident(s,eol,tokenbuf);
a687059c
LW
2535 str_ncat(str, t, s - t);
2536 t = s;
0f85fab0 2537 if (s < eol && *s && index("$'\"",*s))
a687059c
LW
2538 str_ncat(str, ",", 1);
2539 break;
2540 case '"': case '\'':
2541 str_ncat(str, t, s - t);
2542 t = s;
2543 s++;
0f85fab0 2544 while (s < eol && (*s != *t || s[-1] == '\\'))
a687059c 2545 s++;
0f85fab0 2546 if (s < eol)
a687059c
LW
2547 s++;
2548 str_ncat(str, t, s - t);
2549 t = s;
0f85fab0 2550 if (s < eol && *s && index("$'\"",*s))
a687059c
LW
2551 str_ncat(str, ",", 1);
2552 break;
2553 default:
2554 yyerror("Please use commas to separate fields");
378cc40b 2555 }
378cc40b 2556 }
a687059c 2557 str_ncat(str,"$$);",4);
378cc40b 2558 }
378cc40b
LW
2559 }
2560 }
2561 badform:
2562 bufptr = str_get(linestr);
2563 yyerror("Format not terminated");
2564 return froot.f_next;
2565}
a687059c
LW
2566
2567set_csh()
2568{
ae986130
LW
2569#ifdef CSH
2570 if (!cshlen)
2571 cshlen = strlen(cshname);
2572#endif
a687059c 2573}