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

  1. Subject:  v20i099:  Perl, a language with features of C/sed/awk/shell/etc, Part16/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 99
  8. Archive-name: perl3.0/part16
  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 16 (of 24).  If kit 16 is complete, the line"
  16. echo '"'"End of kit 16 (of 24)"'" will echo at the end.'
  17. echo ""
  18. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  19. mkdir x2p 2>/dev/null
  20. echo Extracting x2p/a2py.c
  21. sed >x2p/a2py.c <<'!STUFFY!FUNK!' -e 's/X//'
  22. X/* $Header: a2py.c,v 3.0 89/10/18 15:34:35 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:    a2py.c,v $
  30. X * Revision 3.0  89/10/18  15:34:35  lwall
  31. X * 3.0 baseline
  32. X * 
  33. X */
  34. X
  35. X#include "util.h"
  36. Xchar *index();
  37. X
  38. Xchar *filename;
  39. X
  40. Xint checkers = 0;
  41. XSTR *walk();
  42. X
  43. Xmain(argc,argv,env)
  44. Xregister int argc;
  45. Xregister char **argv;
  46. Xregister char **env;
  47. X{
  48. X    register STR *str;
  49. X    register char *s;
  50. X    int i;
  51. X    STR *tmpstr;
  52. X
  53. X    linestr = str_new(80);
  54. X    str = str_new(0);        /* first used for -I flags */
  55. X    for (argc--,argv++; argc; argc--,argv++) {
  56. X    if (argv[0][0] != '-' || !argv[0][1])
  57. X        break;
  58. X      reswitch:
  59. X    switch (argv[0][1]) {
  60. X#ifdef DEBUGGING
  61. X    case 'D':
  62. X        debug = atoi(argv[0]+2);
  63. X#ifdef YYDEBUG
  64. X        yydebug = (debug & 1);
  65. X#endif
  66. X        break;
  67. X#endif
  68. X    case '0': case '1': case '2': case '3': case '4':
  69. X    case '5': case '6': case '7': case '8': case '9':
  70. X        maxfld = atoi(argv[0]+1);
  71. X        absmaxfld = TRUE;
  72. X        break;
  73. X    case 'F':
  74. X        fswitch = argv[0][2];
  75. X        break;
  76. X    case 'n':
  77. X        namelist = savestr(argv[0]+2);
  78. X        break;
  79. X    case '-':
  80. X        argc--,argv++;
  81. X        goto switch_end;
  82. X    case 0:
  83. X        break;
  84. X    default:
  85. X        fatal("Unrecognized switch: %s\n",argv[0]);
  86. X    }
  87. X    }
  88. X  switch_end:
  89. X
  90. X    /* open script */
  91. X
  92. X    if (argv[0] == Nullch)
  93. X    argv[0] = "-";
  94. X    filename = savestr(argv[0]);
  95. X    if (strEQ(filename,"-"))
  96. X    argv[0] = "";
  97. X    if (!*argv[0])
  98. X    rsfp = stdin;
  99. X    else
  100. X    rsfp = fopen(argv[0],"r");
  101. X    if (rsfp == Nullfp)
  102. X    fatal("Awk script \"%s\" doesn't seem to exist.\n",filename);
  103. X
  104. X    /* init tokener */
  105. X
  106. X    bufptr = str_get(linestr);
  107. X    symtab = hnew();
  108. X    curarghash = hnew();
  109. X
  110. X    /* now parse the report spec */
  111. X
  112. X    if (yyparse())
  113. X    fatal("Translation aborted due to syntax errors.\n");
  114. X
  115. X#ifdef DEBUGGING
  116. X    if (debug & 2) {
  117. X    int type, len;
  118. X
  119. X    for (i=1; i<mop;) {
  120. X        type = ops[i].ival;
  121. X        len = type >> 8;
  122. X        type &= 255;
  123. X        printf("%d\t%d\t%d\t%-10s",i++,type,len,opname[type]);
  124. X        if (type == OSTRING)
  125. X        printf("\t\"%s\"\n",ops[i].cval),i++;
  126. X        else {
  127. X        while (len--) {
  128. X            printf("\t%d",ops[i].ival),i++;
  129. X        }
  130. X        putchar('\n');
  131. X        }
  132. X    }
  133. X    }
  134. X    if (debug & 8)
  135. X    dump(root);
  136. X#endif
  137. X
  138. X    /* first pass to look for numeric variables */
  139. X
  140. X    prewalk(0,0,root,&i);
  141. X
  142. X    /* second pass to produce new program */
  143. X
  144. X    tmpstr = walk(0,0,root,&i,P_MIN);
  145. X    str = str_make("#!");
  146. X    str_cat(str, BIN);
  147. X    str_cat(str, "/perl\neval \"exec ");
  148. X    str_cat(str, BIN);
  149. X    str_cat(str, "/perl -S $0 $*\"\n\
  150. X    if $running_under_some_shell;\n\
  151. X            # this emulates #! processing on NIH machines.\n\
  152. X            # (remove #! line above if indigestible)\n\n");
  153. X    str_cat(str,
  154. X      "eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;\n");
  155. X    str_cat(str,
  156. X      "            # process any FOO=bar switches\n\n");
  157. X    if (do_opens && opens) {
  158. X    str_scat(str,opens);
  159. X    str_free(opens);
  160. X    str_cat(str,"\n");
  161. X    }
  162. X    str_scat(str,tmpstr);
  163. X    str_free(tmpstr);
  164. X#ifdef DEBUGGING
  165. X    if (!(debug & 16))
  166. X#endif
  167. X    fixup(str);
  168. X    putlines(str);
  169. X    if (checkers) {
  170. X    fprintf(stderr,
  171. X      "Please check my work on the %d line%s I've marked with \"#???\".\n",
  172. X        checkers, checkers == 1 ? "" : "s" );
  173. X    fprintf(stderr,
  174. X      "The operation I've selected may be wrong for the operand types.\n");
  175. X    }
  176. X    exit(0);
  177. X}
  178. X
  179. X#define RETURN(retval) return (bufptr = s,retval)
  180. X#define XTERM(retval) return (expectterm = TRUE,bufptr = s,retval)
  181. X#define XOP(retval) return (expectterm = FALSE,bufptr = s,retval)
  182. X#define ID(x) return (yylval=string(x,0),expectterm = FALSE,bufptr = s,idtype)
  183. X
  184. Xint idtype;
  185. X
  186. Xyylex()
  187. X{
  188. X    register char *s = bufptr;
  189. X    register char *d;
  190. X    register int tmp;
  191. X
  192. X  retry:
  193. X#ifdef YYDEBUG
  194. X    if (yydebug)
  195. X    if (index(s,'\n'))
  196. X        fprintf(stderr,"Tokener at %s",s);
  197. X    else
  198. X        fprintf(stderr,"Tokener at %s\n",s);
  199. X#endif
  200. X    switch (*s) {
  201. X    default:
  202. X    fprintf(stderr,
  203. X        "Unrecognized character %c in file %s line %d--ignoring.\n",
  204. X         *s++,filename,line);
  205. X    goto retry;
  206. X    case '\\':
  207. X    case 0:
  208. X    s = str_get(linestr);
  209. X    *s = '\0';
  210. X    if (!rsfp)
  211. X        RETURN(0);
  212. X    line++;
  213. X    if ((s = str_gets(linestr, rsfp)) == Nullch) {
  214. X        if (rsfp != stdin)
  215. X        fclose(rsfp);
  216. X        rsfp = Nullfp;
  217. X        s = str_get(linestr);
  218. X        RETURN(0);
  219. X    }
  220. X    goto retry;
  221. X    case ' ': case '\t':
  222. X    s++;
  223. X    goto retry;
  224. X    case '\n':
  225. X    *s = '\0';
  226. X    XTERM(NEWLINE);
  227. X    case '#':
  228. X    yylval = string(s,0);
  229. X    *s = '\0';
  230. X    XTERM(COMMENT);
  231. X    case ';':
  232. X    tmp = *s++;
  233. X    if (*s == '\n') {
  234. X        s++;
  235. X        XTERM(SEMINEW);
  236. X    }
  237. X    XTERM(tmp);
  238. X    case '(':
  239. X    tmp = *s++;
  240. X    XTERM(tmp);
  241. X    case '{':
  242. X    case '[':
  243. X    case ')':
  244. X    case ']':
  245. X    case '?':
  246. X    case ':':
  247. X    tmp = *s++;
  248. X    XOP(tmp);
  249. X    case 127:
  250. X    s++;
  251. X    XTERM('}');
  252. X    case '}':
  253. X    for (d = s + 1; isspace(*d); d++) ;
  254. X    if (!*d)
  255. X        s = d - 1;
  256. X    *s = 127;
  257. X    XTERM(';');
  258. X    case ',':
  259. X    tmp = *s++;
  260. X    XTERM(tmp);
  261. X    case '~':
  262. X    s++;
  263. X    yylval = string("~",1);
  264. X    XTERM(MATCHOP);
  265. X    case '+':
  266. X    case '-':
  267. X    if (s[1] == *s) {
  268. X        s++;
  269. X        if (*s++ == '+')
  270. X        XTERM(INCR);
  271. X        else
  272. X        XTERM(DECR);
  273. X    }
  274. X    /* FALL THROUGH */
  275. X    case '*':
  276. X    case '%':
  277. X    case '^':
  278. X    tmp = *s++;
  279. X    if (*s == '=') {
  280. X        if (tmp == '^')
  281. X        yylval = string("**=",3);
  282. X        else
  283. X        yylval = string(s-1,2);
  284. X        s++;
  285. X        XTERM(ASGNOP);
  286. X    }
  287. X    XTERM(tmp);
  288. X    case '&':
  289. X    s++;
  290. X    tmp = *s++;
  291. X    if (tmp == '&')
  292. X        XTERM(ANDAND);
  293. X    s--;
  294. X    XTERM('&');
  295. X    case '|':
  296. X    s++;
  297. X    tmp = *s++;
  298. X    if (tmp == '|')
  299. X        XTERM(OROR);
  300. X    s--;
  301. X    while (*s == ' ' || *s == '\t')
  302. X        s++;
  303. X    if (strnEQ(s,"getline",7))
  304. X        XTERM('p');
  305. X    else
  306. X        XTERM('|');
  307. X    case '=':
  308. X    s++;
  309. X    tmp = *s++;
  310. X    if (tmp == '=') {
  311. X        yylval = string("==",2);
  312. X        XTERM(RELOP);
  313. X    }
  314. X    s--;
  315. X    yylval = string("=",1);
  316. X    XTERM(ASGNOP);
  317. X    case '!':
  318. X    s++;
  319. X    tmp = *s++;
  320. X    if (tmp == '=') {
  321. X        yylval = string("!=",2);
  322. X        XTERM(RELOP);
  323. X    }
  324. X    if (tmp == '~') {
  325. X        yylval = string("!~",2);
  326. X        XTERM(MATCHOP);
  327. X    }
  328. X    s--;
  329. X    XTERM(NOT);
  330. X    case '<':
  331. X    s++;
  332. X    tmp = *s++;
  333. X    if (tmp == '=') {
  334. X        yylval = string("<=",2);
  335. X        XTERM(RELOP);
  336. X    }
  337. X    s--;
  338. X    XTERM('<');
  339. X    case '>':
  340. X    s++;
  341. X    tmp = *s++;
  342. X    if (tmp == '>') {
  343. X        yylval = string(">>",2);
  344. X        XTERM(GRGR);
  345. X    }
  346. X    if (tmp == '=') {
  347. X        yylval = string(">=",2);
  348. X        XTERM(RELOP);
  349. X    }
  350. X    s--;
  351. X    XTERM('>');
  352. X
  353. X#define SNARFWORD \
  354. X    d = tokenbuf; \
  355. X    while (isalpha(*s) || isdigit(*s) || *s == '_') \
  356. X        *d++ = *s++; \
  357. X    *d = '\0'; \
  358. X    d = tokenbuf; \
  359. X    if (*s == '(') \
  360. X        idtype = USERFUN; \
  361. X    else \
  362. X        idtype = VAR;
  363. X
  364. X    case '$':
  365. X    s++;
  366. X    if (*s == '0') {
  367. X        s++;
  368. X        do_chop = TRUE;
  369. X        need_entire = TRUE;
  370. X        idtype = VAR;
  371. X        ID("0");
  372. X    }
  373. X    do_split = TRUE;
  374. X    if (isdigit(*s)) {
  375. X        for (d = s; isdigit(*s); s++) ;
  376. X        yylval = string(d,s-d);
  377. X        tmp = atoi(d);
  378. X        if (tmp > maxfld)
  379. X        maxfld = tmp;
  380. X        XOP(FIELD);
  381. X    }
  382. X    split_to_array = set_array_base = TRUE;
  383. X    XOP(VFIELD);
  384. X
  385. X    case '/':            /* may either be division or pattern */
  386. X    if (expectterm) {
  387. X        s = scanpat(s);
  388. X        XTERM(REGEX);
  389. X    }
  390. X    tmp = *s++;
  391. X    if (*s == '=') {
  392. X        yylval = string("/=",2);
  393. X        s++;
  394. X        XTERM(ASGNOP);
  395. X    }
  396. X    XTERM(tmp);
  397. X
  398. X    case '0': case '1': case '2': case '3': case '4':
  399. X    case '5': case '6': case '7': case '8': case '9': case '.':
  400. X    s = scannum(s);
  401. X    XOP(NUMBER);
  402. X    case '"':
  403. X    s++;
  404. X    s = cpy2(tokenbuf,s,s[-1]);
  405. X    if (!*s)
  406. X        fatal("String not terminated:\n%s",str_get(linestr));
  407. X    s++;
  408. X    yylval = string(tokenbuf,0);
  409. X    XOP(STRING);
  410. X
  411. X    case 'a': case 'A':
  412. X    SNARFWORD;
  413. X    if (strEQ(d,"ARGC"))
  414. X        set_array_base = TRUE;
  415. X    if (strEQ(d,"ARGV")) {
  416. X        yylval=numary(string("ARGV",0));
  417. X        XOP(VAR);
  418. X    }
  419. X    if (strEQ(d,"atan2")) {
  420. X        yylval = OATAN2;
  421. X        XTERM(FUNN);
  422. X    }
  423. X    ID(d);
  424. X    case 'b': case 'B':
  425. X    SNARFWORD;
  426. X    if (strEQ(d,"break"))
  427. X        XTERM(BREAK);
  428. X    if (strEQ(d,"BEGIN"))
  429. X        XTERM(BEGIN);
  430. X    ID(d);
  431. X    case 'c': case 'C':
  432. X    SNARFWORD;
  433. X    if (strEQ(d,"continue"))
  434. X        XTERM(CONTINUE);
  435. X    if (strEQ(d,"cos")) {
  436. X        yylval = OCOS;
  437. X        XTERM(FUN1);
  438. X    }
  439. X    if (strEQ(d,"close")) {
  440. X        do_fancy_opens = 1;
  441. X        yylval = OCLOSE;
  442. X        XTERM(FUN1);
  443. X    }
  444. X    if (strEQ(d,"chdir"))
  445. X        *d = toupper(*d);
  446. X    else if (strEQ(d,"crypt"))
  447. X        *d = toupper(*d);
  448. X    else if (strEQ(d,"chop"))
  449. X        *d = toupper(*d);
  450. X    else if (strEQ(d,"chmod"))
  451. X        *d = toupper(*d);
  452. X    else if (strEQ(d,"chown"))
  453. X        *d = toupper(*d);
  454. X    ID(d);
  455. X    case 'd': case 'D':
  456. X    SNARFWORD;
  457. X    if (strEQ(d,"do"))
  458. X        XTERM(DO);
  459. X    if (strEQ(d,"delete"))
  460. X        XTERM(DELETE);
  461. X    if (strEQ(d,"die"))
  462. X        *d = toupper(*d);
  463. X    ID(d);
  464. X    case 'e': case 'E':
  465. X    SNARFWORD;
  466. X    if (strEQ(d,"END"))
  467. X        XTERM(END);
  468. X    if (strEQ(d,"else"))
  469. X        XTERM(ELSE);
  470. X    if (strEQ(d,"exit")) {
  471. X        saw_line_op = TRUE;
  472. X        XTERM(EXIT);
  473. X    }
  474. X    if (strEQ(d,"exp")) {
  475. X        yylval = OEXP;
  476. X        XTERM(FUN1);
  477. X    }
  478. X    if (strEQ(d,"elsif"))
  479. X        *d = toupper(*d);
  480. X    else if (strEQ(d,"eq"))
  481. X        *d = toupper(*d);
  482. X    else if (strEQ(d,"eval"))
  483. X        *d = toupper(*d);
  484. X    else if (strEQ(d,"eof"))
  485. X        *d = toupper(*d);
  486. X    else if (strEQ(d,"each"))
  487. X        *d = toupper(*d);
  488. X    else if (strEQ(d,"exec"))
  489. X        *d = toupper(*d);
  490. X    ID(d);
  491. X    case 'f': case 'F':
  492. X    SNARFWORD;
  493. X    if (strEQ(d,"FS")) {
  494. X        saw_FS++;
  495. X        if (saw_FS == 1 && in_begin) {
  496. X        for (d = s; *d && isspace(*d); d++) ;
  497. X        if (*d == '=') {
  498. X            for (d++; *d && isspace(*d); d++) ;
  499. X            if (*d == '"' && d[2] == '"')
  500. X            const_FS = d[1];
  501. X        }
  502. X        }
  503. X        ID(tokenbuf);
  504. X    }
  505. X    if (strEQ(d,"for"))
  506. X        XTERM(FOR);
  507. X    else if (strEQ(d,"function"))
  508. X        XTERM(FUNCTION);
  509. X    if (strEQ(d,"FILENAME"))
  510. X        d = "ARGV";
  511. X    if (strEQ(d,"foreach"))
  512. X        *d = toupper(*d);
  513. X    else if (strEQ(d,"format"))
  514. X        *d = toupper(*d);
  515. X    else if (strEQ(d,"fork"))
  516. X        *d = toupper(*d);
  517. X    else if (strEQ(d,"fh"))
  518. X        *d = toupper(*d);
  519. X    ID(d);
  520. X    case 'g': case 'G':
  521. X    SNARFWORD;
  522. X    if (strEQ(d,"getline"))
  523. X        XTERM(GETLINE);
  524. X    if (strEQ(d,"gsub"))
  525. X        XTERM(GSUB);
  526. X    if (strEQ(d,"ge"))
  527. X        *d = toupper(*d);
  528. X    else if (strEQ(d,"gt"))
  529. X        *d = toupper(*d);
  530. X    else if (strEQ(d,"goto"))
  531. X        *d = toupper(*d);
  532. X    else if (strEQ(d,"gmtime"))
  533. X        *d = toupper(*d);
  534. X    ID(d);
  535. X    case 'h': case 'H':
  536. X    SNARFWORD;
  537. X    if (strEQ(d,"hex"))
  538. X        *d = toupper(*d);
  539. X    ID(d);
  540. X    case 'i': case 'I':
  541. X    SNARFWORD;
  542. X    if (strEQ(d,"if"))
  543. X        XTERM(IF);
  544. X    if (strEQ(d,"in"))
  545. X        XTERM(IN);
  546. X    if (strEQ(d,"index")) {
  547. X        set_array_base = TRUE;
  548. X        XTERM(INDEX);
  549. X    }
  550. X    if (strEQ(d,"int")) {
  551. X        yylval = OINT;
  552. X        XTERM(FUN1);
  553. X    }
  554. X    ID(d);
  555. X    case 'j': case 'J':
  556. X    SNARFWORD;
  557. X    if (strEQ(d,"join"))
  558. X        *d = toupper(*d);
  559. X    ID(d);
  560. X    case 'k': case 'K':
  561. X    SNARFWORD;
  562. X    if (strEQ(d,"keys"))
  563. X        *d = toupper(*d);
  564. X    else if (strEQ(d,"kill"))
  565. X        *d = toupper(*d);
  566. X    ID(d);
  567. X    case 'l': case 'L':
  568. X    SNARFWORD;
  569. X    if (strEQ(d,"length")) {
  570. X        yylval = OLENGTH;
  571. X        XTERM(FUN1);
  572. X    }
  573. X    if (strEQ(d,"log")) {
  574. X        yylval = OLOG;
  575. X        XTERM(FUN1);
  576. X    }
  577. X    if (strEQ(d,"last"))
  578. X        *d = toupper(*d);
  579. X    else if (strEQ(d,"local"))
  580. X        *d = toupper(*d);
  581. X    else if (strEQ(d,"lt"))
  582. X        *d = toupper(*d);
  583. X    else if (strEQ(d,"le"))
  584. X        *d = toupper(*d);
  585. X    else if (strEQ(d,"locatime"))
  586. X        *d = toupper(*d);
  587. X    else if (strEQ(d,"link"))
  588. X        *d = toupper(*d);
  589. X    ID(d);
  590. X    case 'm': case 'M':
  591. X    SNARFWORD;
  592. X    if (strEQ(d,"match")) {
  593. X        set_array_base = TRUE;
  594. X        XTERM(MATCH);
  595. X    }
  596. X    if (strEQ(d,"m"))
  597. X        *d = toupper(*d);
  598. X    ID(d);
  599. X    case 'n': case 'N':
  600. X    SNARFWORD;
  601. X    if (strEQ(d,"NF"))
  602. X        do_split = split_to_array = set_array_base = TRUE;
  603. X    if (strEQ(d,"next")) {
  604. X        saw_line_op = TRUE;
  605. X        XTERM(NEXT);
  606. X    }
  607. X    if (strEQ(d,"ne"))
  608. X        *d = toupper(*d);
  609. X    ID(d);
  610. X    case 'o': case 'O':
  611. X    SNARFWORD;
  612. X    if (strEQ(d,"ORS")) {
  613. X        saw_ORS = TRUE;
  614. X        d = "\\";
  615. X    }
  616. X    if (strEQ(d,"OFS")) {
  617. X        saw_OFS = TRUE;
  618. X        d = ",";
  619. X    }
  620. X    if (strEQ(d,"OFMT")) {
  621. X        d = "#";
  622. X    }
  623. X    if (strEQ(d,"open"))
  624. X        *d = toupper(*d);
  625. X    else if (strEQ(d,"ord"))
  626. X        *d = toupper(*d);
  627. X    else if (strEQ(d,"oct"))
  628. X        *d = toupper(*d);
  629. X    ID(d);
  630. X    case 'p': case 'P':
  631. X    SNARFWORD;
  632. X    if (strEQ(d,"print")) {
  633. X        XTERM(PRINT);
  634. X    }
  635. X    if (strEQ(d,"printf")) {
  636. X        XTERM(PRINTF);
  637. X    }
  638. X    if (strEQ(d,"push"))
  639. X        *d = toupper(*d);
  640. X    else if (strEQ(d,"pop"))
  641. X        *d = toupper(*d);
  642. X    ID(d);
  643. X    case 'q': case 'Q':
  644. X    SNARFWORD;
  645. X    ID(d);
  646. X    case 'r': case 'R':
  647. X    SNARFWORD;
  648. X    if (strEQ(d,"RS")) {
  649. X        d = "/";
  650. X        saw_RS = TRUE;
  651. X    }
  652. X    if (strEQ(d,"rand")) {
  653. X        yylval = ORAND;
  654. X        XTERM(FUN1);
  655. X    }
  656. X    if (strEQ(d,"return"))
  657. X        XTERM(RET);
  658. X    if (strEQ(d,"reset"))
  659. X        *d = toupper(*d);
  660. X    else if (strEQ(d,"redo"))
  661. X        *d = toupper(*d);
  662. X    else if (strEQ(d,"rename"))
  663. X        *d = toupper(*d);
  664. X    ID(d);
  665. X    case 's': case 'S':
  666. X    SNARFWORD;
  667. X    if (strEQ(d,"split")) {
  668. X        set_array_base = TRUE;
  669. X        XOP(SPLIT);
  670. X    }
  671. X    if (strEQ(d,"substr")) {
  672. X        set_array_base = TRUE;
  673. X        XTERM(SUBSTR);
  674. X    }
  675. X    if (strEQ(d,"sub"))
  676. X        XTERM(SUB);
  677. X    if (strEQ(d,"sprintf"))
  678. X        XTERM(SPRINTF);
  679. X    if (strEQ(d,"sqrt")) {
  680. X        yylval = OSQRT;
  681. X        XTERM(FUN1);
  682. X    }
  683. X    if (strEQ(d,"SUBSEP")) {
  684. X        d = ";";
  685. X    }
  686. X    if (strEQ(d,"sin")) {
  687. X        yylval = OSIN;
  688. X        XTERM(FUN1);
  689. X    }
  690. X    if (strEQ(d,"srand")) {
  691. X        yylval = OSRAND;
  692. X        XTERM(FUN1);
  693. X    }
  694. X    if (strEQ(d,"system")) {
  695. X        yylval = OSYSTEM;
  696. X        XTERM(FUN1);
  697. X    }
  698. X    if (strEQ(d,"s"))
  699. X        *d = toupper(*d);
  700. X    else if (strEQ(d,"shift"))
  701. X        *d = toupper(*d);
  702. X    else if (strEQ(d,"select"))
  703. X        *d = toupper(*d);
  704. X    else if (strEQ(d,"seek"))
  705. X        *d = toupper(*d);
  706. X    else if (strEQ(d,"stat"))
  707. X        *d = toupper(*d);
  708. X    else if (strEQ(d,"study"))
  709. X        *d = toupper(*d);
  710. X    else if (strEQ(d,"sleep"))
  711. X        *d = toupper(*d);
  712. X    else if (strEQ(d,"symlink"))
  713. X        *d = toupper(*d);
  714. X    else if (strEQ(d,"sort"))
  715. X        *d = toupper(*d);
  716. X    ID(d);
  717. X    case 't': case 'T':
  718. X    SNARFWORD;
  719. X    if (strEQ(d,"tr"))
  720. X        *d = toupper(*d);
  721. X    else if (strEQ(d,"tell"))
  722. X        *d = toupper(*d);
  723. X    else if (strEQ(d,"time"))
  724. X        *d = toupper(*d);
  725. X    else if (strEQ(d,"times"))
  726. X        *d = toupper(*d);
  727. X    ID(d);
  728. X    case 'u': case 'U':
  729. X    SNARFWORD;
  730. X    if (strEQ(d,"until"))
  731. X        *d = toupper(*d);
  732. X    else if (strEQ(d,"unless"))
  733. X        *d = toupper(*d);
  734. X    else if (strEQ(d,"umask"))
  735. X        *d = toupper(*d);
  736. X    else if (strEQ(d,"unshift"))
  737. X        *d = toupper(*d);
  738. X    else if (strEQ(d,"unlink"))
  739. X        *d = toupper(*d);
  740. X    else if (strEQ(d,"utime"))
  741. X        *d = toupper(*d);
  742. X    ID(d);
  743. X    case 'v': case 'V':
  744. X    SNARFWORD;
  745. X    if (strEQ(d,"values"))
  746. X        *d = toupper(*d);
  747. X    ID(d);
  748. X    case 'w': case 'W':
  749. X    SNARFWORD;
  750. X    if (strEQ(d,"while"))
  751. X        XTERM(WHILE);
  752. X    if (strEQ(d,"write"))
  753. X        *d = toupper(*d);
  754. X    else if (strEQ(d,"wait"))
  755. X        *d = toupper(*d);
  756. X    ID(d);
  757. X    case 'x': case 'X':
  758. X    SNARFWORD;
  759. X    if (strEQ(d,"x"))
  760. X        *d = toupper(*d);
  761. X    ID(d);
  762. X    case 'y': case 'Y':
  763. X    SNARFWORD;
  764. X    if (strEQ(d,"y"))
  765. X        *d = toupper(*d);
  766. X    ID(d);
  767. X    case 'z': case 'Z':
  768. X    SNARFWORD;
  769. X    ID(d);
  770. X    }
  771. X}
  772. X
  773. Xchar *
  774. Xscanpat(s)
  775. Xregister char *s;
  776. X{
  777. X    register char *d;
  778. X
  779. X    switch (*s++) {
  780. X    case '/':
  781. X    break;
  782. X    default:
  783. X    fatal("Search pattern not found:\n%s",str_get(linestr));
  784. X    }
  785. X
  786. X    d = tokenbuf;
  787. X    for (; *s; s++,d++) {
  788. X    if (*s == '\\') {
  789. X        if (s[1] == '/')
  790. X        *d++ = *s++;
  791. X        else if (s[1] == '\\')
  792. X        *d++ = *s++;
  793. X    }
  794. X    else if (*s == '[') {
  795. X        *d++ = *s++;
  796. X        do {
  797. X        if (*s == '\\' && s[1])
  798. X            *d++ = *s++;
  799. X        if (*s == '/' || (*s == '-' && s[1] == ']'))
  800. X            *d++ = '\\';
  801. X        *d++ = *s++;
  802. X        } while (*s && *s != ']');
  803. X    }
  804. X    else if (*s == '/')
  805. X        break;
  806. X    *d = *s;
  807. X    }
  808. X    *d = '\0';
  809. X
  810. X    if (!*s)
  811. X    fatal("Search pattern not terminated:\n%s",str_get(linestr));
  812. X    s++;
  813. X    yylval = string(tokenbuf,0);
  814. X    return s;
  815. X}
  816. X
  817. Xyyerror(s)
  818. Xchar *s;
  819. X{
  820. X    fprintf(stderr,"%s in file %s at line %d\n",
  821. X      s,filename,line);
  822. X}
  823. X
  824. Xchar *
  825. Xscannum(s)
  826. Xregister char *s;
  827. X{
  828. X    register char *d;
  829. X
  830. X    switch (*s) {
  831. X    case '1': case '2': case '3': case '4': case '5':
  832. X    case '6': case '7': case '8': case '9': case '0' : case '.':
  833. X    d = tokenbuf;
  834. X    while (isdigit(*s)) {
  835. X        *d++ = *s++;
  836. X    }
  837. X    if (*s == '.' && index("0123456789eE",s[1])) {
  838. X        *d++ = *s++;
  839. X        while (isdigit(*s)) {
  840. X        *d++ = *s++;
  841. X        }
  842. X    }
  843. X    if (index("eE",*s) && index("+-0123456789",s[1])) {
  844. X        *d++ = *s++;
  845. X        if (*s == '+' || *s == '-')
  846. X        *d++ = *s++;
  847. X        while (isdigit(*s))
  848. X        *d++ = *s++;
  849. X    }
  850. X    *d = '\0';
  851. X    yylval = string(tokenbuf,0);
  852. X    break;
  853. X    }
  854. X    return s;
  855. X}
  856. X
  857. Xstring(ptr,len)
  858. Xchar *ptr;
  859. X{
  860. X    int retval = mop;
  861. X
  862. X    ops[mop++].ival = OSTRING + (1<<8);
  863. X    if (!len)
  864. X    len = strlen(ptr);
  865. X    ops[mop].cval = safemalloc(len+1);
  866. X    strncpy(ops[mop].cval,ptr,len);
  867. X    ops[mop++].cval[len] = '\0';
  868. X    if (mop >= OPSMAX)
  869. X    fatal("Recompile a2p with larger OPSMAX\n");
  870. X    return retval;
  871. X}
  872. X
  873. Xoper0(type)
  874. Xint type;
  875. X{
  876. X    int retval = mop;
  877. X
  878. X    if (type > 255)
  879. X    fatal("type > 255 (%d)\n",type);
  880. X    ops[mop++].ival = type;
  881. X    if (mop >= OPSMAX)
  882. X    fatal("Recompile a2p with larger OPSMAX\n");
  883. X    return retval;
  884. X}
  885. X
  886. Xoper1(type,arg1)
  887. Xint type;
  888. Xint arg1;
  889. X{
  890. X    int retval = mop;
  891. X
  892. X    if (type > 255)
  893. X    fatal("type > 255 (%d)\n",type);
  894. X    ops[mop++].ival = type + (1<<8);
  895. X    ops[mop++].ival = arg1;
  896. X    if (mop >= OPSMAX)
  897. X    fatal("Recompile a2p with larger OPSMAX\n");
  898. X    return retval;
  899. X}
  900. X
  901. Xoper2(type,arg1,arg2)
  902. Xint type;
  903. Xint arg1;
  904. Xint arg2;
  905. X{
  906. X    int retval = mop;
  907. X
  908. X    if (type > 255)
  909. X    fatal("type > 255 (%d)\n",type);
  910. X    ops[mop++].ival = type + (2<<8);
  911. X    ops[mop++].ival = arg1;
  912. X    ops[mop++].ival = arg2;
  913. X    if (mop >= OPSMAX)
  914. X    fatal("Recompile a2p with larger OPSMAX\n");
  915. X    return retval;
  916. X}
  917. X
  918. Xoper3(type,arg1,arg2,arg3)
  919. Xint type;
  920. Xint arg1;
  921. Xint arg2;
  922. Xint arg3;
  923. X{
  924. X    int retval = mop;
  925. X
  926. X    if (type > 255)
  927. X    fatal("type > 255 (%d)\n",type);
  928. X    ops[mop++].ival = type + (3<<8);
  929. X    ops[mop++].ival = arg1;
  930. X    ops[mop++].ival = arg2;
  931. X    ops[mop++].ival = arg3;
  932. X    if (mop >= OPSMAX)
  933. X    fatal("Recompile a2p with larger OPSMAX\n");
  934. X    return retval;
  935. X}
  936. X
  937. Xoper4(type,arg1,arg2,arg3,arg4)
  938. Xint type;
  939. Xint arg1;
  940. Xint arg2;
  941. Xint arg3;
  942. Xint arg4;
  943. X{
  944. X    int retval = mop;
  945. X
  946. X    if (type > 255)
  947. X    fatal("type > 255 (%d)\n",type);
  948. X    ops[mop++].ival = type + (4<<8);
  949. X    ops[mop++].ival = arg1;
  950. X    ops[mop++].ival = arg2;
  951. X    ops[mop++].ival = arg3;
  952. X    ops[mop++].ival = arg4;
  953. X    if (mop >= OPSMAX)
  954. X    fatal("Recompile a2p with larger OPSMAX\n");
  955. X    return retval;
  956. X}
  957. X
  958. Xoper5(type,arg1,arg2,arg3,arg4,arg5)
  959. Xint type;
  960. Xint arg1;
  961. Xint arg2;
  962. Xint arg3;
  963. Xint arg4;
  964. Xint arg5;
  965. X{
  966. X    int retval = mop;
  967. X
  968. X    if (type > 255)
  969. X    fatal("type > 255 (%d)\n",type);
  970. X    ops[mop++].ival = type + (5<<8);
  971. X    ops[mop++].ival = arg1;
  972. X    ops[mop++].ival = arg2;
  973. X    ops[mop++].ival = arg3;
  974. X    ops[mop++].ival = arg4;
  975. X    ops[mop++].ival = arg5;
  976. X    if (mop >= OPSMAX)
  977. X    fatal("Recompile a2p with larger OPSMAX\n");
  978. X    return retval;
  979. X}
  980. X
  981. Xint depth = 0;
  982. X
  983. Xdump(branch)
  984. Xint branch;
  985. X{
  986. X    register int type;
  987. X    register int len;
  988. X    register int i;
  989. X
  990. X    type = ops[branch].ival;
  991. X    len = type >> 8;
  992. X    type &= 255;
  993. X    for (i=depth; i; i--)
  994. X    printf(" ");
  995. X    if (type == OSTRING) {
  996. X    printf("%-5d\"%s\"\n",branch,ops[branch+1].cval);
  997. X    }
  998. X    else {
  999. X    printf("(%-5d%s %d\n",branch,opname[type],len);
  1000. X    depth++;
  1001. X    for (i=1; i<=len; i++)
  1002. X        dump(ops[branch+i].ival);
  1003. X    depth--;
  1004. X    for (i=depth; i; i--)
  1005. X        printf(" ");
  1006. X    printf(")\n");
  1007. X    }
  1008. X}
  1009. X
  1010. Xbl(arg,maybe)
  1011. Xint arg;
  1012. Xint maybe;
  1013. X{
  1014. X    if (!arg)
  1015. X    return 0;
  1016. X    else if ((ops[arg].ival & 255) != OBLOCK)
  1017. X    return oper2(OBLOCK,arg,maybe);
  1018. X    else if ((ops[arg].ival >> 8) < 2)
  1019. X    return oper2(OBLOCK,ops[arg+1].ival,maybe);
  1020. X    else
  1021. X    return arg;
  1022. X}
  1023. X
  1024. Xfixup(str)
  1025. XSTR *str;
  1026. X{
  1027. X    register char *s;
  1028. X    register char *t;
  1029. X
  1030. X    for (s = str->str_ptr; *s; s++) {
  1031. X    if (*s == ';' && s[1] == ' ' && s[2] == '\n') {
  1032. X        strcpy(s+1,s+2);
  1033. X        s++;
  1034. X    }
  1035. X    else if (*s == '\n') {
  1036. X        for (t = s+1; isspace(*t & 127); t++) ;
  1037. X        t--;
  1038. X        while (isspace(*t & 127) && *t != '\n') t--;
  1039. X        if (*t == '\n' && t-s > 1) {
  1040. X        if (s[-1] == '{')
  1041. X            s--;
  1042. X        strcpy(s+1,t);
  1043. X        }
  1044. X        s++;
  1045. X    }
  1046. X    }
  1047. X}
  1048. X
  1049. Xputlines(str)
  1050. XSTR *str;
  1051. X{
  1052. X    register char *d, *s, *t, *e;
  1053. X    register int pos, newpos;
  1054. X
  1055. X    d = tokenbuf;
  1056. X    pos = 0;
  1057. X    for (s = str->str_ptr; *s; s++) {
  1058. X    *d++ = *s;
  1059. X    pos++;
  1060. X    if (*s == '\n') {
  1061. X        *d = '\0';
  1062. X        d = tokenbuf;
  1063. X        pos = 0;
  1064. X        putone();
  1065. X    }
  1066. X    else if (*s == '\t')
  1067. X        pos += 7;
  1068. X    if (pos > 78) {        /* split a long line? */
  1069. X        *d-- = '\0';
  1070. X        newpos = 0;
  1071. X        for (t = tokenbuf; isspace(*t & 127); t++) {
  1072. X        if (*t == '\t')
  1073. X            newpos += 8;
  1074. X        else
  1075. X            newpos += 1;
  1076. X        }
  1077. X        e = d;
  1078. X        while (d > tokenbuf && (*d != ' ' || d[-1] != ';'))
  1079. X        d--;
  1080. X        if (d < t+10) {
  1081. X        d = e;
  1082. X        while (d > tokenbuf &&
  1083. X          (*d != ' ' || d[-1] != '|' || d[-2] != '|') )
  1084. X            d--;
  1085. X        }
  1086. X        if (d < t+10) {
  1087. X        d = e;
  1088. X        while (d > tokenbuf &&
  1089. X          (*d != ' ' || d[-1] != '&' || d[-2] != '&') )
  1090. X            d--;
  1091. X        }
  1092. X        if (d < t+10) {
  1093. X        d = e;
  1094. X        while (d > tokenbuf && (*d != ' ' || d[-1] != ','))
  1095. X            d--;
  1096. X        }
  1097. X        if (d < t+10) {
  1098. X        d = e;
  1099. X        while (d > tokenbuf && *d != ' ')
  1100. X            d--;
  1101. X        }
  1102. X        if (d > t+3) {
  1103. X        *d = '\0';
  1104. X        putone();
  1105. X        putchar('\n');
  1106. X        if (d[-1] != ';' && !(newpos % 4)) {
  1107. X            *t++ = ' ';
  1108. X            *t++ = ' ';
  1109. X            newpos += 2;
  1110. X        }
  1111. X        strcpy(t,d+1);
  1112. X        newpos += strlen(t);
  1113. X        d = t + strlen(t);
  1114. X        pos = newpos;
  1115. X        }
  1116. X        else
  1117. X        d = e + 1;
  1118. X    }
  1119. X    }
  1120. X}
  1121. X
  1122. Xputone()
  1123. X{
  1124. X    register char *t;
  1125. X
  1126. X    for (t = tokenbuf; *t; t++) {
  1127. X    *t &= 127;
  1128. X    if (*t == 127) {
  1129. X        *t = ' ';
  1130. X        strcpy(t+strlen(t)-1, "\t#???\n");
  1131. X        checkers++;
  1132. X    }
  1133. X    }
  1134. X    t = tokenbuf;
  1135. X    if (*t == '#') {
  1136. X    if (strnEQ(t,"#!/bin/awk",10) || strnEQ(t,"#! /bin/awk",11))
  1137. X        return;
  1138. X    if (strnEQ(t,"#!/usr/bin/awk",14) || strnEQ(t,"#! /usr/bin/awk",15))
  1139. X        return;
  1140. X    }
  1141. X    fputs(tokenbuf,stdout);
  1142. X}
  1143. X
  1144. Xnumary(arg)
  1145. Xint arg;
  1146. X{
  1147. X    STR *key;
  1148. X    int dummy;
  1149. X
  1150. X    key = walk(0,0,arg,&dummy,P_MIN);
  1151. X    str_cat(key,"[]");
  1152. X    hstore(symtab,key->str_ptr,str_make("1"));
  1153. X    str_free(key);
  1154. X    set_array_base = TRUE;
  1155. X    return arg;
  1156. X}
  1157. X
  1158. Xrememberargs(arg)
  1159. Xint arg;
  1160. X{
  1161. X    int type;
  1162. X    STR *str;
  1163. X
  1164. X    if (!arg)
  1165. X    return arg;
  1166. X    type = ops[arg].ival & 255;
  1167. X    if (type == OCOMMA) {
  1168. X    rememberargs(ops[arg+1].ival);
  1169. X    rememberargs(ops[arg+3].ival);
  1170. X    }
  1171. X    else if (type == OVAR) {
  1172. X    str = str_new(0);
  1173. X    hstore(curarghash,ops[ops[arg+1].ival+1].cval,str);
  1174. X    }
  1175. X    else
  1176. X    fatal("panic: unknown argument type %d, line %d\n",type,line);
  1177. X    return arg;
  1178. X}
  1179. X
  1180. Xaryrefarg(arg)
  1181. Xint arg;
  1182. X{
  1183. X    int type = ops[arg].ival & 255;
  1184. X    STR *str;
  1185. X
  1186. X    if (type != OSTRING)
  1187. X    fatal("panic: aryrefarg %d, line %d\n",type,line);
  1188. X    str = hfetch(curarghash,ops[arg+1].cval);
  1189. X    if (str)
  1190. X    str_set(str,"*");
  1191. X    return arg;
  1192. X}
  1193. X
  1194. Xfixfargs(name,arg,prevargs)
  1195. Xint name;
  1196. Xint arg;
  1197. Xint prevargs;
  1198. X{
  1199. X    int type;
  1200. X    STR *str;
  1201. X    int numargs;
  1202. X
  1203. X    if (!arg)
  1204. X    return prevargs;
  1205. X    type = ops[arg].ival & 255;
  1206. X    if (type == OCOMMA) {
  1207. X    numargs = fixfargs(name,ops[arg+1].ival,prevargs);
  1208. X    numargs = fixfargs(name,ops[arg+3].ival,numargs);
  1209. X    }
  1210. X    else if (type == OVAR) {
  1211. X    str = hfetch(curarghash,ops[ops[arg+1].ival+1].cval);
  1212. X    if (strEQ(str_get(str),"*")) {
  1213. X        char tmpbuf[128];
  1214. X
  1215. X        str_set(str,"");        /* in case another routine has this */
  1216. X        ops[arg].ival &= ~255;
  1217. X        ops[arg].ival |= OSTAR;
  1218. X        sprintf(tmpbuf,"%s:%d",ops[name+1].cval,prevargs);
  1219. X        fprintf(stderr,"Adding %s\n",tmpbuf);
  1220. X        str = str_new(0);
  1221. X        str_set(str,"*");
  1222. X        hstore(curarghash,tmpbuf,str);
  1223. X    }
  1224. X    numargs = prevargs + 1;
  1225. X    }
  1226. X    else
  1227. X    fatal("panic: unknown argument type %d, arg %d, line %d\n",
  1228. X      type,numargs+1,line);
  1229. X    return numargs;
  1230. X}
  1231. X
  1232. Xfixrargs(name,arg,prevargs)
  1233. Xchar *name;
  1234. Xint arg;
  1235. Xint prevargs;
  1236. X{
  1237. X    int type;
  1238. X    STR *str;
  1239. X    int numargs;
  1240. X
  1241. X    if (!arg)
  1242. X    return prevargs;
  1243. X    type = ops[arg].ival & 255;
  1244. X    if (type == OCOMMA) {
  1245. X    numargs = fixrargs(name,ops[arg+1].ival,prevargs);
  1246. X    numargs = fixrargs(name,ops[arg+3].ival,numargs);
  1247. X    }
  1248. X    else {
  1249. X    char tmpbuf[128];
  1250. X
  1251. X    sprintf(tmpbuf,"%s:%d",name,prevargs);
  1252. X    str = hfetch(curarghash,tmpbuf);
  1253. X    fprintf(stderr,"Looking for %s\n",tmpbuf);
  1254. X    if (str && strEQ(str->str_ptr,"*")) {
  1255. X        if (type == OVAR || type == OSTAR) {
  1256. X        ops[arg].ival &= ~255;
  1257. X        ops[arg].ival |= OSTAR;
  1258. X        }
  1259. X        else
  1260. X        fatal("Can't pass expression by reference as arg %d of %s\n",
  1261. X            prevargs+1, name);
  1262. X    }
  1263. X    numargs = prevargs + 1;
  1264. X    }
  1265. X    return numargs;
  1266. X}
  1267. X
  1268. !STUFFY!FUNK!
  1269. echo Extracting dolist.c
  1270. sed >dolist.c <<'!STUFFY!FUNK!' -e 's/X//'
  1271. X/* $Header: dolist.c,v 3.0 89/10/18 15:11:02 lwall Locked $
  1272. X *
  1273. X *    Copyright (c) 1989, Larry Wall
  1274. X *
  1275. X *    You may distribute under the terms of the GNU General Public License
  1276. X *    as specified in the README file that comes with the perl 3.0 kit.
  1277. X *
  1278. X * $Log:    dolist.c,v $
  1279. X * Revision 3.0  89/10/18  15:11:02  lwall
  1280. X * 3.0 baseline
  1281. X * 
  1282. X */
  1283. X
  1284. X#include "EXTERN.h"
  1285. X#include "perl.h"
  1286. X
  1287. X
  1288. Xint
  1289. Xdo_match(str,arg,gimme,arglast)
  1290. XSTR *str;
  1291. Xregister ARG *arg;
  1292. Xint gimme;
  1293. Xint *arglast;
  1294. X{
  1295. X    register STR **st = stack->ary_array;
  1296. X    register SPAT *spat = arg[2].arg_ptr.arg_spat;
  1297. X    register char *t;
  1298. X    register int sp = arglast[0] + 1;
  1299. X    STR *srchstr = st[sp];
  1300. X    register char *s = str_get(st[sp]);
  1301. X    char *strend = s + st[sp]->str_cur;
  1302. X    STR *tmpstr;
  1303. X
  1304. X    if (!spat) {
  1305. X    if (gimme == G_ARRAY)
  1306. X        return --sp;
  1307. X    str_set(str,Yes);
  1308. X    STABSET(str);
  1309. X    st[sp] = str;
  1310. X    return sp;
  1311. X    }
  1312. X    if (!s)
  1313. X    fatal("panic: do_match");
  1314. X    if (spat->spat_flags & SPAT_USED) {
  1315. X#ifdef DEBUGGING
  1316. X    if (debug & 8)
  1317. X        deb("2.SPAT USED\n");
  1318. X#endif
  1319. X    if (gimme == G_ARRAY)
  1320. X        return --sp;
  1321. X    str_set(str,No);
  1322. X    STABSET(str);
  1323. X    st[sp] = str;
  1324. X    return sp;
  1325. X    }
  1326. X    --sp;
  1327. X    if (spat->spat_runtime) {
  1328. X    nointrp = "|)";
  1329. X    sp = eval(spat->spat_runtime,G_SCALAR,sp);
  1330. X    st = stack->ary_array;
  1331. X    t = str_get(tmpstr = st[sp--]);
  1332. X    nointrp = "";
  1333. X#ifdef DEBUGGING
  1334. X    if (debug & 8)
  1335. X        deb("2.SPAT /%s/\n",t);
  1336. X#endif
  1337. X    if (spat->spat_regexp)
  1338. X        regfree(spat->spat_regexp);
  1339. X    spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,
  1340. X        spat->spat_flags & SPAT_FOLD,1);
  1341. X    if (!*spat->spat_regexp->precomp && lastspat)
  1342. X        spat = lastspat;
  1343. X    if (spat->spat_flags & SPAT_KEEP) {
  1344. X        arg_free(spat->spat_runtime);    /* it won't change, so */
  1345. X        spat->spat_runtime = Nullarg;    /* no point compiling again */
  1346. X    }
  1347. X    if (!spat->spat_regexp->nparens)
  1348. X        gimme = G_SCALAR;            /* accidental array context? */
  1349. X    if (regexec(spat->spat_regexp, s, strend, s, 0,
  1350. X      srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
  1351. X      gimme == G_ARRAY)) {
  1352. X        if (spat->spat_regexp->subbase)
  1353. X        curspat = spat;
  1354. X        lastspat = spat;
  1355. X        goto gotcha;
  1356. X    }
  1357. X    else {
  1358. X        if (gimme == G_ARRAY)
  1359. X        return sp;
  1360. X        str_sset(str,&str_no);
  1361. X        STABSET(str);
  1362. X        st[++sp] = str;
  1363. X        return sp;
  1364. X    }
  1365. X    }
  1366. X    else {
  1367. X#ifdef DEBUGGING
  1368. X    if (debug & 8) {
  1369. X        char ch;
  1370. X
  1371. X        if (spat->spat_flags & SPAT_ONCE)
  1372. X        ch = '?';
  1373. X        else
  1374. X        ch = '/';
  1375. X        deb("2.SPAT %c%s%c\n",ch,spat->spat_regexp->precomp,ch);
  1376. X    }
  1377. X#endif
  1378. X    if (!*spat->spat_regexp->precomp && lastspat)
  1379. X        spat = lastspat;
  1380. X    t = s;
  1381. X    if (hint) {
  1382. X        if (hint < s || hint > strend)
  1383. X        fatal("panic: hint in do_match");
  1384. X        s = hint;
  1385. X        hint = Nullch;
  1386. X        if (spat->spat_regexp->regback >= 0) {
  1387. X        s -= spat->spat_regexp->regback;
  1388. X        if (s < t)
  1389. X            s = t;
  1390. X        }
  1391. X        else
  1392. X        s = t;
  1393. X    }
  1394. X    else if (spat->spat_short) {
  1395. X        if (spat->spat_flags & SPAT_SCANFIRST) {
  1396. X        if (srchstr->str_pok & SP_STUDIED) {
  1397. X            if (screamfirst[spat->spat_short->str_rare] < 0)
  1398. X            goto nope;
  1399. X            else if (!(s = screaminstr(srchstr,spat->spat_short)))
  1400. X            goto nope;
  1401. X            else if (spat->spat_flags & SPAT_ALL)
  1402. X            goto yup;
  1403. X        }
  1404. X#ifndef lint
  1405. X        else if (!(s = fbminstr((unsigned char*)s,
  1406. X          (unsigned char*)strend, spat->spat_short)))
  1407. X            goto nope;
  1408. X#endif
  1409. X        else if (spat->spat_flags & SPAT_ALL)
  1410. X            goto yup;
  1411. X        if (s && spat->spat_regexp->regback >= 0) {
  1412. X            ++spat->spat_short->str_u.str_useful;
  1413. X            s -= spat->spat_regexp->regback;
  1414. X            if (s < t)
  1415. X            s = t;
  1416. X        }
  1417. X        else
  1418. X            s = t;
  1419. X        }
  1420. X        else if (!multiline && (*spat->spat_short->str_ptr != *s ||
  1421. X          bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
  1422. X        goto nope;
  1423. X        if (--spat->spat_short->str_u.str_useful < 0) {
  1424. X        str_free(spat->spat_short);
  1425. X        spat->spat_short = Nullstr;    /* opt is being useless */
  1426. X        }
  1427. X    }
  1428. X    if (!spat->spat_regexp->nparens)
  1429. X        gimme = G_SCALAR;            /* accidental array context? */
  1430. X    if (regexec(spat->spat_regexp, s, strend, t, 0,
  1431. X      srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
  1432. X      gimme == G_ARRAY)) {
  1433. X        if (spat->spat_regexp->subbase)
  1434. X        curspat = spat;
  1435. X        lastspat = spat;
  1436. X        if (spat->spat_flags & SPAT_ONCE)
  1437. X        spat->spat_flags |= SPAT_USED;
  1438. X        goto gotcha;
  1439. X    }
  1440. X    else {
  1441. X        if (gimme == G_ARRAY)
  1442. X        return sp;
  1443. X        str_sset(str,&str_no);
  1444. X        STABSET(str);
  1445. X        st[++sp] = str;
  1446. X        return sp;
  1447. X    }
  1448. X    }
  1449. X    /*NOTREACHED*/
  1450. X
  1451. X  gotcha:
  1452. X    if (gimme == G_ARRAY) {
  1453. X    int iters, i, len;
  1454. X
  1455. X    iters = spat->spat_regexp->nparens;
  1456. X    if (sp + iters >= stack->ary_max) {
  1457. X        astore(stack,sp + iters, Nullstr);
  1458. X        st = stack->ary_array;        /* possibly realloced */
  1459. X    }
  1460. X
  1461. X    for (i = 1; i <= iters; i++) {
  1462. X        st[++sp] = str_static(&str_no);
  1463. X        if (s = spat->spat_regexp->startp[i]) {
  1464. X        len = spat->spat_regexp->endp[i] - s;
  1465. X        if (len > 0)
  1466. X            str_nset(st[sp],s,len);
  1467. X        }
  1468. X    }
  1469. X    return sp;
  1470. X    }
  1471. X    else {
  1472. X    str_sset(str,&str_yes);
  1473. X    STABSET(str);
  1474. X    st[++sp] = str;
  1475. X    return sp;
  1476. X    }
  1477. X
  1478. Xyup:
  1479. X    ++spat->spat_short->str_u.str_useful;
  1480. X    lastspat = spat;
  1481. X    if (spat->spat_flags & SPAT_ONCE)
  1482. X    spat->spat_flags |= SPAT_USED;
  1483. X    if (sawampersand) {
  1484. X    char *tmps;
  1485. X
  1486. X    tmps = spat->spat_regexp->subbase = nsavestr(t,strend-t);
  1487. X    tmps = spat->spat_regexp->startp[0] = tmps + (s - t);
  1488. X    spat->spat_regexp->endp[0] = tmps + spat->spat_short->str_cur;
  1489. X    curspat = spat;
  1490. X    }
  1491. X    str_sset(str,&str_yes);
  1492. X    STABSET(str);
  1493. X    st[++sp] = str;
  1494. X    return sp;
  1495. X
  1496. Xnope:
  1497. X    ++spat->spat_short->str_u.str_useful;
  1498. X    if (gimme == G_ARRAY)
  1499. X    return sp;
  1500. X    str_sset(str,&str_no);
  1501. X    STABSET(str);
  1502. X    st[++sp] = str;
  1503. X    return sp;
  1504. X}
  1505. X
  1506. Xint
  1507. Xdo_split(str,spat,limit,gimme,arglast)
  1508. XSTR *str;
  1509. Xregister SPAT *spat;
  1510. Xregister int limit;
  1511. Xint gimme;
  1512. Xint *arglast;
  1513. X{
  1514. X    register ARRAY *ary = stack;
  1515. X    STR **st = ary->ary_array;
  1516. X    register int sp = arglast[0] + 1;
  1517. X    register char *s = str_get(st[sp]);
  1518. X    char *strend = s + st[sp--]->str_cur;
  1519. X    register STR *dstr;
  1520. X    register char *m;
  1521. X    int iters = 0;
  1522. X    int i;
  1523. X    char *orig;
  1524. X    int origlimit = limit;
  1525. X    int realarray = 0;
  1526. X
  1527. X    if (!spat || !s)
  1528. X    fatal("panic: do_split");
  1529. X    else if (spat->spat_runtime) {
  1530. X    nointrp = "|)";
  1531. X    sp = eval(spat->spat_runtime,G_SCALAR,sp);
  1532. X    st = stack->ary_array;
  1533. X    m = str_get(dstr = st[sp--]);
  1534. X    nointrp = "";
  1535. X    if (!dstr->str_cur || (*m == ' ' && dstr->str_cur == 1)) {
  1536. X        str_set(dstr,"\\s+");
  1537. X        m = dstr->str_ptr;
  1538. X        spat->spat_flags |= SPAT_SKIPWHITE;
  1539. X    }
  1540. X    if (spat->spat_regexp)
  1541. X        regfree(spat->spat_regexp);
  1542. X    spat->spat_regexp = regcomp(m,m+dstr->str_cur,
  1543. X        spat->spat_flags & SPAT_FOLD,1);
  1544. X    if (spat->spat_flags & SPAT_KEEP ||
  1545. X        (spat->spat_runtime->arg_type == O_ITEM &&
  1546. X          (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
  1547. X        arg_free(spat->spat_runtime);    /* it won't change, so */
  1548. X        spat->spat_runtime = Nullarg;    /* no point compiling again */
  1549. X    }
  1550. X    }
  1551. X#ifdef DEBUGGING
  1552. X    if (debug & 8) {
  1553. X    deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
  1554. X    }
  1555. X#endif
  1556. X    ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
  1557. X    if (ary && ((ary->ary_flags & ARF_REAL) || gimme != G_ARRAY)) {
  1558. X    ary->ary_flags |= ARF_REAL;
  1559. X    realarray = 1;
  1560. X    ary->ary_fill = -1;
  1561. X    sp = -1;    /* temporarily switch stacks */
  1562. X    }
  1563. X    else
  1564. X    ary = stack;
  1565. X    orig = s;
  1566. X    if (spat->spat_flags & SPAT_SKIPWHITE) {
  1567. X    while (isspace(*s))
  1568. X        s++;
  1569. X    }
  1570. X    if (!limit)
  1571. X    limit = 10001;
  1572. X    if (spat->spat_short) {
  1573. X    i = spat->spat_short->str_cur;
  1574. X    if (i == 1) {
  1575. X        i = *spat->spat_short->str_ptr;
  1576. X        while (--limit) {
  1577. X        for (m = s; m < strend && *m != i; m++) ;
  1578. X        if (m >= strend)
  1579. X            break;
  1580. X        if (realarray)
  1581. X            dstr = Str_new(30,m-s);
  1582. X        else
  1583. X            dstr = str_static(&str_undef);
  1584. X        str_nset(dstr,s,m-s);
  1585. X        (void)astore(ary, ++sp, dstr);
  1586. X        s = m + 1;
  1587. X        }
  1588. X    }
  1589. X    else {
  1590. X#ifndef lint
  1591. X        while (s < strend && --limit &&
  1592. X          (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
  1593. X            spat->spat_short)) )
  1594. X#endif
  1595. X        {
  1596. X        if (realarray)
  1597. X            dstr = Str_new(31,m-s);
  1598. X        else
  1599. X            dstr = str_static(&str_undef);
  1600. X        str_nset(dstr,s,m-s);
  1601. X        (void)astore(ary, ++sp, dstr);
  1602. X        s = m + i;
  1603. X        }
  1604. X    }
  1605. X    }
  1606. X    else {
  1607. X    while (s < strend && --limit &&
  1608. X        regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
  1609. X        if (spat->spat_regexp->subbase
  1610. X          && spat->spat_regexp->subbase != orig) {
  1611. X        m = s;
  1612. X        s = orig;
  1613. X        orig = spat->spat_regexp->subbase;
  1614. X        s = orig + (m - s);
  1615. X        strend = s + (strend - m);
  1616. X        }
  1617. X        m = spat->spat_regexp->startp[0];
  1618. X        if (realarray)
  1619. X        dstr = Str_new(32,m-s);
  1620. X        else
  1621. X        dstr = str_static(&str_undef);
  1622. X        str_nset(dstr,s,m-s);
  1623. X        (void)astore(ary, ++sp, dstr);
  1624. X        if (spat->spat_regexp->nparens) {
  1625. X        for (i = 1; i <= spat->spat_regexp->nparens; i++) {
  1626. X            s = spat->spat_regexp->startp[i];
  1627. X            m = spat->spat_regexp->endp[i];
  1628. X            if (realarray)
  1629. X            dstr = Str_new(33,m-s);
  1630. X            else
  1631. X            dstr = str_static(&str_undef);
  1632. X            str_nset(dstr,s,m-s);
  1633. X            (void)astore(ary, ++sp, dstr);
  1634. X        }
  1635. X        }
  1636. X        s = spat->spat_regexp->endp[0];
  1637. X    }
  1638. X    }
  1639. X    if (realarray)
  1640. X    iters = sp + 1;
  1641. X    else
  1642. X    iters = sp - arglast[0];
  1643. X    if (iters > 9999)
  1644. X    fatal("Split loop");
  1645. X    if (s < strend || origlimit) {    /* keep field after final delim? */
  1646. X    if (realarray)
  1647. X        dstr = Str_new(34,strend-s);
  1648. X    else
  1649. X        dstr = str_static(&str_undef);
  1650. X    str_nset(dstr,s,strend-s);
  1651. X    (void)astore(ary, ++sp, dstr);
  1652. X    iters++;
  1653. X    }
  1654. X    else {
  1655. X#ifndef I286
  1656. X    while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
  1657. X        iters--,sp--;
  1658. X#else
  1659. X    char *zaps;
  1660. X    int   zapb;
  1661. X
  1662. X    if (iters > 0) {
  1663. X        zaps = str_get(afetch(ary,sp,FALSE));
  1664. X        zapb = (int) *zaps;
  1665. X    }
  1666. X    
  1667. X    while (iters > 0 && (!zapb)) {
  1668. X        iters--,sp--;
  1669. X        if (iters > 0) {
  1670. X        zaps = str_get(afetch(ary,iters-1,FALSE));
  1671. X        zapb = (int) *zaps;
  1672. X        }
  1673. X    }
  1674. X#endif
  1675. X    }
  1676. X    if (realarray) {
  1677. X    ary->ary_fill = sp;
  1678. X    if (gimme == G_ARRAY) {
  1679. X        sp++;
  1680. X        astore(stack, arglast[0] + 1 + sp, Nullstr);
  1681. X        Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
  1682. X        return arglast[0] + sp;
  1683. X    }
  1684. X    }
  1685. X    else {
  1686. X    if (gimme == G_ARRAY)
  1687. X        return sp;
  1688. X    }
  1689. X    sp = arglast[0] + 1;
  1690. X    str_numset(str,(double)iters);
  1691. X    STABSET(str);
  1692. X    st[sp] = str;
  1693. X    return sp;
  1694. X}
  1695. X
  1696. Xint
  1697. Xdo_unpack(str,gimme,arglast)
  1698. XSTR *str;
  1699. Xint gimme;
  1700. Xint *arglast;
  1701. X{
  1702. X    STR **st = stack->ary_array;
  1703. X    register int sp = arglast[0] + 1;
  1704. X    register char *pat = str_get(st[sp++]);
  1705. X    register char *s = str_get(st[sp]);
  1706. X    char *strend = s + st[sp--]->str_cur;
  1707. X    register char *patend = pat + st[sp]->str_cur;
  1708. X    int datumtype;
  1709. X    register int len;
  1710. X
  1711. X    /* These must not be in registers: */
  1712. X    char achar;
  1713. X    short ashort;
  1714. X    int aint;
  1715. X    long along;
  1716. X    unsigned char auchar;
  1717. X    unsigned short aushort;
  1718. X    unsigned int auint;
  1719. X    unsigned long aulong;
  1720. X    char *aptr;
  1721. X
  1722. X    if (gimme != G_ARRAY) {
  1723. X    str_sset(str,&str_undef);
  1724. X    STABSET(str);
  1725. X    st[sp] = str;
  1726. X    return sp;
  1727. X    }
  1728. X    sp--;
  1729. X    while (pat < patend) {
  1730. X    datumtype = *pat++;
  1731. X    if (isdigit(*pat)) {
  1732. X        len = atoi(pat);
  1733. X        while (isdigit(*pat))
  1734. X        pat++;
  1735. X    }
  1736. X    else
  1737. X        len = 1;
  1738. X    switch(datumtype) {
  1739. X    default:
  1740. X        break;
  1741. X    case 'x':
  1742. X        s += len;
  1743. X        break;
  1744. X    case 'A':
  1745. X    case 'a':
  1746. X        if (s + len > strend)
  1747. X        len = strend - s;
  1748. X        str = Str_new(35,len);
  1749. X        str_nset(str,s,len);
  1750. X        s += len;
  1751. X        if (datumtype == 'A') {
  1752. X        aptr = s;    /* borrow register */
  1753. X        s = str->str_ptr + len - 1;
  1754. X        while (s >= str->str_ptr && (!*s || isspace(*s)))
  1755. X            s--;
  1756. X        *++s = '\0';
  1757. X        str->str_cur = s - str->str_ptr;
  1758. X        s = aptr;    /* unborrow register */
  1759. X        }
  1760. X        (void)astore(stack, ++sp, str_2static(str));
  1761. X        break;
  1762. X    case 'c':
  1763. X        while (len-- > 0) {
  1764. X        if (s + sizeof(char) > strend)
  1765. X            achar = 0;
  1766. X        else {
  1767. X            bcopy(s,(char*)&achar,sizeof(char));
  1768. X            s += sizeof(char);
  1769. X        }
  1770. X        str = Str_new(36,0);
  1771. X        aint = achar;
  1772. X        if (aint >= 128)    /* fake up signed chars */
  1773. X            aint -= 256;
  1774. X        str_numset(str,(double)aint);
  1775. X        (void)astore(stack, ++sp, str_2static(str));
  1776. X        }
  1777. X        break;
  1778. X    case 'C':
  1779. X        while (len-- > 0) {
  1780. X        if (s + sizeof(unsigned char) > strend)
  1781. X            auchar = 0;
  1782. X        else {
  1783. X            bcopy(s,(char*)&auchar,sizeof(unsigned char));
  1784. X            s += sizeof(unsigned char);
  1785. X        }
  1786. X        str = Str_new(37,0);
  1787. X        auint = auchar;        /* some can't cast uchar to double */
  1788. X        str_numset(str,(double)auint);
  1789. X        (void)astore(stack, ++sp, str_2static(str));
  1790. X        }
  1791. X        break;
  1792. X    case 's':
  1793. X        while (len-- > 0) {
  1794. X        if (s + sizeof(short) > strend)
  1795. X            ashort = 0;
  1796. X        else {
  1797. X            bcopy(s,(char*)&ashort,sizeof(short));
  1798. X            s += sizeof(short);
  1799. X        }
  1800. X        str = Str_new(38,0);
  1801. X        str_numset(str,(double)ashort);
  1802. X        (void)astore(stack, ++sp, str_2static(str));
  1803. X        }
  1804. X        break;
  1805. X    case 'n':
  1806. X    case 'S':
  1807. X        while (len-- > 0) {
  1808. X        if (s + sizeof(unsigned short) > strend)
  1809. X            aushort = 0;
  1810. X        else {
  1811. X            bcopy(s,(char*)&aushort,sizeof(unsigned short));
  1812. X            s += sizeof(unsigned short);
  1813. X        }
  1814. X        str = Str_new(39,0);
  1815. X#ifdef NTOHS
  1816. X        if (datumtype == 'n')
  1817. X            aushort = ntohs(aushort);
  1818. X#endif
  1819. X        str_numset(str,(double)aushort);
  1820. X        (void)astore(stack, ++sp, str_2static(str));
  1821. X        }
  1822. X        break;
  1823. X    case 'i':
  1824. X        while (len-- > 0) {
  1825. X        if (s + sizeof(int) > strend)
  1826. X            aint = 0;
  1827. X        else {
  1828. X            bcopy(s,(char*)&aint,sizeof(int));
  1829. X            s += sizeof(int);
  1830. X        }
  1831. X        str = Str_new(40,0);
  1832. X        str_numset(str,(double)aint);
  1833. X        (void)astore(stack, ++sp, str_2static(str));
  1834. X        }
  1835. X        break;
  1836. X    case 'I':
  1837. X        while (len-- > 0) {
  1838. X        if (s + sizeof(unsigned int) > strend)
  1839. X            auint = 0;
  1840. X        else {
  1841. X            bcopy(s,(char*)&auint,sizeof(unsigned int));
  1842. X            s += sizeof(unsigned int);
  1843. X        }
  1844. X        str = Str_new(41,0);
  1845. X        str_numset(str,(double)auint);
  1846. X        (void)astore(stack, ++sp, str_2static(str));
  1847. X        }
  1848. X        break;
  1849. X    case 'l':
  1850. X        while (len-- > 0) {
  1851. X        if (s + sizeof(long) > strend)
  1852. X            along = 0;
  1853. X        else {
  1854. X            bcopy(s,(char*)&along,sizeof(long));
  1855. X            s += sizeof(long);
  1856. X        }
  1857. X        str = Str_new(42,0);
  1858. X        str_numset(str,(double)along);
  1859. X        (void)astore(stack, ++sp, str_2static(str));
  1860. X        }
  1861. X        break;
  1862. X    case 'N':
  1863. X    case 'L':
  1864. X        while (len-- > 0) {
  1865. X        if (s + sizeof(unsigned long) > strend)
  1866. X            aulong = 0;
  1867. X        else {
  1868. X            bcopy(s,(char*)&aulong,sizeof(unsigned long));
  1869. X            s += sizeof(unsigned long);
  1870. X        }
  1871. X        str = Str_new(43,0);
  1872. X#ifdef NTOHL
  1873. X        if (datumtype == 'N')
  1874. X            aulong = ntohl(aulong);
  1875. X#endif
  1876. X        str_numset(str,(double)aulong);
  1877. X        (void)astore(stack, ++sp, str_2static(str));
  1878. X        }
  1879. X        break;
  1880. X    case 'p':
  1881. X        while (len-- > 0) {
  1882. X        if (s + sizeof(char*) > strend)
  1883. X            aptr = 0;
  1884. X        else {
  1885. X            bcopy(s,(char*)&aptr,sizeof(char*));
  1886. X            s += sizeof(char*);
  1887. X        }
  1888. X        str = Str_new(44,0);
  1889. X        if (aptr)
  1890. X            str_set(str,aptr);
  1891. X        (void)astore(stack, ++sp, str_2static(str));
  1892. X        }
  1893. X        break;
  1894. X    }
  1895. X    }
  1896. X    return sp;
  1897. X}
  1898. X
  1899. Xint
  1900. Xdo_slice(stab,numarray,lval,gimme,arglast)
  1901. Xregister STAB *stab;
  1902. Xint numarray;
  1903. Xint lval;
  1904. Xint gimme;
  1905. Xint *arglast;
  1906. X{
  1907. X    register STR **st = stack->ary_array;
  1908. X    register int sp = arglast[1];
  1909. X    register int max = arglast[2];
  1910. X    register char *tmps;
  1911. X    register int len;
  1912. X    register int magic = 0;
  1913. X
  1914. X    if (lval && !numarray) {
  1915. X    if (stab == envstab)
  1916. X        magic = 'E';
  1917. X    else if (stab == sigstab)
  1918. X        magic = 'S';
  1919. X#ifdef SOME_DBM
  1920. X    else if (stab_hash(stab)->tbl_dbm)
  1921. X        magic = 'D';
  1922. X#endif /* SOME_DBM */
  1923. X    }
  1924. X
  1925. X    if (gimme == G_ARRAY) {
  1926. X    if (numarray) {
  1927. X        while (sp < max) {
  1928. X        if (st[++sp]) {
  1929. X            st[sp-1] = afetch(stab_array(stab),(int)str_gnum(st[sp]),
  1930. X            lval);
  1931. X        }
  1932. X        else
  1933. X            st[sp-1] = Nullstr;
  1934. X        }
  1935. X    }
  1936. X    else {
  1937. X        while (sp < max) {
  1938. X        if (st[++sp]) {
  1939. X            tmps = str_get(st[sp]);
  1940. X            len = st[sp]->str_cur;
  1941. X            st[sp-1] = hfetch(stab_hash(stab),tmps,len, lval);
  1942. X            if (magic)
  1943. X            str_magic(st[sp-1],stab,magic,tmps,len);
  1944. X        }
  1945. X        else
  1946. X            st[sp-1] = Nullstr;
  1947. X        }
  1948. X    }
  1949. X    sp--;
  1950. X    }
  1951. X    else {
  1952. X    if (numarray) {
  1953. X        if (st[max])
  1954. X        st[sp] = afetch(stab_array(stab),(int)str_gnum(st[max]), lval);
  1955. X        else
  1956. X        st[sp] = Nullstr;
  1957. X    }
  1958. X    else {
  1959. X        if (st[max]) {
  1960. X        tmps = str_get(st[max]);
  1961. X        len = st[max]->str_cur;
  1962. X        st[sp] = hfetch(stab_hash(stab),tmps,len, lval);
  1963. X        if (magic)
  1964. X            str_magic(st[sp],stab,magic,tmps,len);
  1965. X        }
  1966. X        else
  1967. X        st[sp] = Nullstr;
  1968. X    }
  1969. X    }
  1970. X    return sp;
  1971. X}
  1972. X
  1973. Xint
  1974. Xdo_grep(arg,str,gimme,arglast)
  1975. Xregister ARG *arg;
  1976. XSTR *str;
  1977. Xint gimme;
  1978. Xint *arglast;
  1979. X{
  1980. X    STR **st = stack->ary_array;
  1981. X    register STR **dst = &st[arglast[1]];
  1982. X    register STR **src = dst + 1;
  1983. X    register int sp = arglast[2];
  1984. X    register int i = sp - arglast[1];
  1985. X    int oldsave = savestack->ary_fill;
  1986. X
  1987. X    savesptr(&stab_val(defstab));
  1988. X    if ((arg[1].arg_type & A_MASK) != A_EXPR)
  1989. X    dehoist(arg,1);
  1990. X    arg = arg[1].arg_ptr.arg_arg;
  1991. X    while (i-- > 0) {
  1992. X    stab_val(defstab) = *src;
  1993. X    (void)eval(arg,G_SCALAR,sp);
  1994. X    if (str_true(st[sp+1]))
  1995. X        *dst++ = *src;
  1996. X    src++;
  1997. X    }
  1998. X    restorelist(oldsave);
  1999. X    if (gimme != G_ARRAY) {
  2000. X    str_sset(str,&str_undef);
  2001. X    STABSET(str);
  2002. X    st[arglast[0]+1] = str;
  2003. X    return arglast[0]+1;
  2004. X    }
  2005. X    return arglast[0] + (dst - &st[arglast[1]]);
  2006. X}
  2007. X
  2008. Xint
  2009. Xdo_reverse(str,gimme,arglast)
  2010. XSTR *str;
  2011. Xint gimme;
  2012. Xint *arglast;
  2013. X{
  2014. X    STR **st = stack->ary_array;
  2015. X    register STR **up = &st[arglast[1]];
  2016. X    register STR **down = &st[arglast[2]];
  2017. X    register int i = arglast[2] - arglast[1];
  2018. X
  2019. X    if (gimme != G_ARRAY) {
  2020. X    str_sset(str,&str_undef);
  2021. X    STABSET(str);
  2022. X    st[arglast[0]+1] = str;
  2023. X    return arglast[0]+1;
  2024. X    }
  2025. X    while (i-- > 0) {
  2026. X    *up++ = *down;
  2027. X    *down-- = *up;
  2028. X    }
  2029. X    return arglast[2] - 1;
  2030. X}
  2031. X
  2032. Xstatic CMD *sortcmd;
  2033. Xstatic STAB *firststab = Nullstab;
  2034. Xstatic STAB *secondstab = Nullstab;
  2035. X
  2036. Xint
  2037. Xdo_sort(str,stab,gimme,arglast)
  2038. XSTR *str;
  2039. XSTAB *stab;
  2040. Xint gimme;
  2041. Xint *arglast;
  2042. X{
  2043. X    STR **st = stack->ary_array;
  2044. X    int sp = arglast[1];
  2045. X    register STR **up;
  2046. X    register int max = arglast[2] - sp;
  2047. X    register int i;
  2048. X    int sortcmp();
  2049. X    int sortsub();
  2050. X    STR *oldfirst;
  2051. X    STR *oldsecond;
  2052. X    ARRAY *oldstack;
  2053. X    static ARRAY *sortstack = Null(ARRAY*);
  2054. X
  2055. X    if (gimme != G_ARRAY) {
  2056. X    str_sset(str,&str_undef);
  2057. X    STABSET(str);
  2058. X    st[sp] = str;
  2059. X    return sp;
  2060. X    }
  2061. X    up = &st[sp];
  2062. X    for (i = 0; i < max; i++) {
  2063. X    if ((*up = up[1]) && !(*up)->str_pok)
  2064. X        (void)str_2ptr(*up);
  2065. X    up++;
  2066. X    }
  2067. X    sp--;
  2068. X    if (max > 1) {
  2069. X    if (stab_sub(stab) && (sortcmd = stab_sub(stab)->cmd)) {
  2070. X        int oldtmps_base = tmps_base;
  2071. X
  2072. X        if (!sortstack) {
  2073. X        sortstack = anew(Nullstab);
  2074. X        sortstack->ary_flags = 0;
  2075. X        }
  2076. X        oldstack = stack;
  2077. X        stack = sortstack;
  2078. X        tmps_base = tmps_max;
  2079. X        if (!firststab) {
  2080. X        firststab = stabent("a",TRUE);
  2081. X        secondstab = stabent("b",TRUE);
  2082. X        }
  2083. X        oldfirst = stab_val(firststab);
  2084. X        oldsecond = stab_val(secondstab);
  2085. X#ifndef lint
  2086. X        qsort((char*)(st+sp+1),max,sizeof(STR*),sortsub);
  2087. X#else
  2088. X        qsort(Nullch,max,sizeof(STR*),sortsub);
  2089. X#endif
  2090. X        stab_val(firststab) = oldfirst;
  2091. X        stab_val(secondstab) = oldsecond;
  2092. X        tmps_base = oldtmps_base;
  2093. X        stack = oldstack;
  2094. X    }
  2095. X#ifndef lint
  2096. X    else
  2097. X        qsort((char*)(st+sp+1),max,sizeof(STR*),sortcmp);
  2098. X#endif
  2099. X    }
  2100. X    up = &st[arglast[1]];
  2101. X    while (max > 0 && !*up)
  2102. X    max--,up--;
  2103. X    return sp+max;
  2104. X}
  2105. X
  2106. Xint
  2107. Xsortsub(str1,str2)
  2108. XSTR **str1;
  2109. XSTR **str2;
  2110. X{
  2111. X    if (!*str1)
  2112. X    return -1;
  2113. X    if (!*str2)
  2114. X    return 1;
  2115. X    stab_val(firststab) = *str1;
  2116. X    stab_val(secondstab) = *str2;
  2117. X    cmd_exec(sortcmd,G_SCALAR,-1);
  2118. X    return (int)str_gnum(*stack->ary_array);
  2119. X}
  2120. X
  2121. Xsortcmp(strp1,strp2)
  2122. XSTR **strp1;
  2123. XSTR **strp2;
  2124. X{
  2125. X    register STR *str1 = *strp1;
  2126. X    register STR *str2 = *strp2;
  2127. X    int retval;
  2128. X
  2129. X    if (!str1)
  2130. X    return -1;
  2131. X    if (!str2)
  2132. X    return 1;
  2133. X
  2134. X    if (str1->str_cur < str2->str_cur) {
  2135. X    if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
  2136. X        return retval;
  2137. X    else
  2138. X        return -1;
  2139. X    }
  2140. X    else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
  2141. X    return retval;
  2142. X    else if (str1->str_cur == str2->str_cur)
  2143. X    return 0;
  2144. X    else
  2145. X    return 1;
  2146. X}
  2147. X
  2148. Xint
  2149. Xdo_range(gimme,arglast)
  2150. Xint gimme;
  2151. Xint *arglast;
  2152. X{
  2153. X    STR **st = stack->ary_array;
  2154. X    register int sp = arglast[0];
  2155. X    register int i = (int)str_gnum(st[sp+1]);
  2156. X    register ARRAY *ary = stack;
  2157. X    register STR *str;
  2158. X    int max = (int)str_gnum(st[sp+2]);
  2159. X
  2160. X    if (gimme != G_ARRAY)
  2161. X    fatal("panic: do_range");
  2162. X
  2163. X    while (i <= max) {
  2164. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  2165. X    str_numset(str,(double)i++);
  2166. X    }
  2167. X    return sp;
  2168. X}
  2169. X
  2170. Xint
  2171. Xdo_tms(str,gimme,arglast)
  2172. XSTR *str;
  2173. Xint gimme;
  2174. Xint *arglast;
  2175. X{
  2176. X    STR **st = stack->ary_array;
  2177. X    register int sp = arglast[0];
  2178. X
  2179. X    if (gimme != G_ARRAY) {
  2180. X    str_sset(str,&str_undef);
  2181. X    STABSET(str);
  2182. X    st[++sp] = str;
  2183. X    return sp;
  2184. X    }
  2185. X    (void)times(×buf);
  2186. X
  2187. X#ifndef HZ
  2188. X#define HZ 60
  2189. X#endif
  2190. X
  2191. X#ifndef lint
  2192. X    (void)astore(stack,++sp,
  2193. X      str_2static(str_nmake(((double)timesbuf.tms_utime)/HZ)));
  2194. X    (void)astore(stack,++sp,
  2195. X      str_2static(str_nmake(((double)timesbuf.tms_stime)/HZ)));
  2196. X    (void)astore(stack,++sp,
  2197. X      str_2static(str_nmake(((double)timesbuf.tms_cutime)/HZ)));
  2198. X    (void)astore(stack,++sp,
  2199. X      str_2static(str_nmake(((double)timesbuf.tms_cstime)/HZ)));
  2200. X#else
  2201. X    (void)astore(stack,++sp,
  2202. X      str_2static(str_nmake(0.0)));
  2203. X#endif
  2204. X    return sp;
  2205. X}
  2206. X
  2207. Xint
  2208. Xdo_time(str,tmbuf,gimme,arglast)
  2209. XSTR *str;
  2210. Xstruct tm *tmbuf;
  2211. Xint gimme;
  2212. Xint *arglast;
  2213. X{
  2214. X    register ARRAY *ary = stack;
  2215. X    STR **st = ary->ary_array;
  2216. X    register int sp = arglast[0];
  2217. X
  2218. X    if (!tmbuf || gimme != G_ARRAY) {
  2219. X    str_sset(str,&str_undef);
  2220. X    STABSET(str);
  2221. X    st[++sp] = str;
  2222. X    return sp;
  2223. X    }
  2224. X    (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_sec)));
  2225. X    (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_min)));
  2226. X    (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_hour)));
  2227. X    (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mday)));
  2228. X    (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mon)));
  2229. X    (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_year)));
  2230. X    (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_wday)));
  2231. X    (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_yday)));
  2232. X    (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_isdst)));
  2233. X    return sp;
  2234. X}
  2235. X
  2236. Xint
  2237. Xdo_kv(str,hash,kv,gimme,arglast)
  2238. XSTR *str;
  2239. XHASH *hash;
  2240. Xint kv;
  2241. Xint gimme;
  2242. Xint *arglast;
  2243. X{
  2244. X    register ARRAY *ary = stack;
  2245. X    STR **st = ary->ary_array;
  2246. X    register int sp = arglast[0];
  2247. X    int i;
  2248. X    register HENT *entry;
  2249. X    char *tmps;
  2250. X    STR *tmpstr;
  2251. X    int dokeys = (kv == O_KEYS || kv == O_HASH);
  2252. X    int dovalues = (kv == O_VALUES || kv == O_HASH);
  2253. X
  2254. X    if (gimme != G_ARRAY) {
  2255. X    str_sset(str,&str_undef);
  2256. X    STABSET(str);
  2257. X    st[++sp] = str;
  2258. X    return sp;
  2259. X    }
  2260. X    (void)hiterinit(hash);
  2261. X    while (entry = hiternext(hash)) {
  2262. X    if (dokeys) {
  2263. X        tmps = hiterkey(entry,&i);
  2264. X        (void)astore(ary,++sp,str_2static(str_make(tmps,i)));
  2265. X    }
  2266. X    if (dovalues) {
  2267. X        tmpstr = Str_new(45,0);
  2268. X#ifdef DEBUGGING
  2269. X        if (debug & 8192) {
  2270. X        sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
  2271. X            hash->tbl_max+1,entry->hent_hash & hash->tbl_max);
  2272. X        str_set(tmpstr,buf);
  2273. X        }
  2274. X        else
  2275. X#endif
  2276. X        str_sset(tmpstr,hiterval(hash,entry));
  2277. X        (void)astore(ary,++sp,str_2static(tmpstr));
  2278. X    }
  2279. X    }
  2280. X    return sp;
  2281. X}
  2282. X
  2283. Xint
  2284. Xdo_each(str,hash,gimme,arglast)
  2285. XSTR *str;
  2286. XHASH *hash;
  2287. Xint gimme;
  2288. Xint *arglast;
  2289. X{
  2290. X    STR **st = stack->ary_array;
  2291. X    register int sp = arglast[0];
  2292. X    static STR *mystrk = Nullstr;
  2293. X    HENT *entry = hiternext(hash);
  2294. X    int i;
  2295. X    char *tmps;
  2296. X
  2297. X    if (mystrk) {
  2298. X    str_free(mystrk);
  2299. X    mystrk = Nullstr;
  2300. X    }
  2301. X
  2302. X    if (entry) {
  2303. X    if (gimme == G_ARRAY) {
  2304. X        tmps = hiterkey(entry, &i);
  2305. X        st[++sp] = mystrk = str_make(tmps,i);
  2306. X    }
  2307. X    st[++sp] = str;
  2308. X    str_sset(str,hiterval(hash,entry));
  2309. X    STABSET(str);
  2310. X    return sp;
  2311. X    }
  2312. X    else
  2313. X    return sp;
  2314. X}
  2315. !STUFFY!FUNK!
  2316. echo ""
  2317. echo "End of kit 16 (of 24)"
  2318. cat /dev/null >kit16isdone
  2319. run=''
  2320. config=''
  2321. 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
  2322.     if test -f kit${iskit}isdone; then
  2323.     run="$run $iskit"
  2324.     else
  2325.     todo="$todo $iskit"
  2326.     fi
  2327. done
  2328. case $todo in
  2329.     '')
  2330.     echo "You have run all your kits.  Please read README and then type Configure."
  2331.     chmod 755 Configure
  2332.     ;;
  2333.     *)  echo "You have run$run."
  2334.     echo "You still need to run$todo."
  2335.     ;;
  2336. esac
  2337. : Someone might mail this, so...
  2338. exit
  2339.  
  2340.