home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume18 / perl / part04 < prev    next >
Internet Message Format  |  1991-04-14  |  52KB

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