home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume20 / perl3.0 / part05 < prev    next >
Encoding:
Internet Message Format  |  1989-10-29  |  49.4 KB

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