home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume13 / perl / part07 < prev    next >
Encoding:
Internet Message Format  |  1988-01-30  |  49.3 KB

  1. Subject:  v13i007:  Perl, a "replacement" for awk and sed, Part07/10
  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 13, Issue 7
  8. Archive-name: perl/part07
  9.  
  10.  
  11.  
  12. #! /bin/sh
  13.  
  14. # Make a new directory for the perl sources, cd to it, and run kits 1
  15. # thru 10 through sh.  When all 10 kits have been run, read README.
  16.  
  17. echo "This is perl 1.0 kit 7 (of 10).  If kit 7 is complete, the line"
  18. echo '"'"End of kit 7 (of 10)"'" will echo at the end.'
  19. echo ""
  20. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  21. mkdir t 2>/dev/null
  22. mkdir x2p 2>/dev/null
  23. echo Extracting x2p/a2py.c
  24. sed >x2p/a2py.c <<'!STUFFY!FUNK!' -e 's/X//'
  25. X/* $Header: a2py.c,v 1.0 87/12/18 17:50:33 root Exp $
  26. X *
  27. X * $Log:    a2py.c,v $
  28. X * Revision 1.0  87/12/18  17:50:33  root
  29. X * Initial revision
  30. X * 
  31. X */
  32. X
  33. X#include "util.h"
  34. Xchar *index();
  35. X
  36. Xchar *filename;
  37. X
  38. Xmain(argc,argv,env)
  39. Xregister int argc;
  40. Xregister char **argv;
  41. Xregister char **env;
  42. X{
  43. X    register STR *str;
  44. X    register char *s;
  45. X    int i;
  46. X    STR *walk();
  47. X    STR *tmpstr;
  48. X
  49. X    linestr = str_new(80);
  50. X    str = str_new(0);        /* first used for -I flags */
  51. X    for (argc--,argv++; argc; argc--,argv++) {
  52. X    if (argv[0][0] != '-' || !argv[0][1])
  53. X        break;
  54. X      reswitch:
  55. X    switch (argv[0][1]) {
  56. X#ifdef DEBUGGING
  57. X    case 'D':
  58. X        debug = atoi(argv[0]+2);
  59. X#ifdef YYDEBUG
  60. X        yydebug = (debug & 1);
  61. X#endif
  62. X        break;
  63. X#endif
  64. X    case '0': case '1': case '2': case '3': case '4':
  65. X    case '5': case '6': case '7': case '8': case '9':
  66. X        maxfld = atoi(argv[0]+1);
  67. X        absmaxfld = TRUE;
  68. X        break;
  69. X    case 'F':
  70. X        fswitch = argv[0][2];
  71. X        break;
  72. X    case 'n':
  73. X        namelist = savestr(argv[0]+2);
  74. X        break;
  75. X    case '-':
  76. X        argc--,argv++;
  77. X        goto switch_end;
  78. X    case 0:
  79. X        break;
  80. X    default:
  81. X        fatal("Unrecognized switch: %s\n",argv[0]);
  82. X    }
  83. X    }
  84. X  switch_end:
  85. X
  86. X    /* open script */
  87. X
  88. X    if (argv[0] == Nullch)
  89. X    argv[0] = "-";
  90. X    filename = savestr(argv[0]);
  91. X    if (strEQ(filename,"-"))
  92. X    argv[0] = "";
  93. X    if (!*argv[0])
  94. X    rsfp = stdin;
  95. X    else
  96. X    rsfp = fopen(argv[0],"r");
  97. X    if (rsfp == Nullfp)
  98. X    fatal("Awk script \"%s\" doesn't seem to exist.\n",filename);
  99. X
  100. X    /* init tokener */
  101. X
  102. X    bufptr = str_get(linestr);
  103. X    symtab = hnew();
  104. X
  105. X    /* now parse the report spec */
  106. X
  107. X    if (yyparse())
  108. X    fatal("Translation aborted due to syntax errors.\n");
  109. X
  110. X#ifdef DEBUGGING
  111. X    if (debug & 2) {
  112. X    int type, len;
  113. X
  114. X    for (i=1; i<mop;) {
  115. X        type = ops[i].ival;
  116. X        len = type >> 8;
  117. X        type &= 255;
  118. X        printf("%d\t%d\t%d\t%-10s",i++,type,len,opname[type]);
  119. X        if (type == OSTRING)
  120. X        printf("\t\"%s\"\n",ops[i].cval),i++;
  121. X        else {
  122. X        while (len--) {
  123. X            printf("\t%d",ops[i].ival),i++;
  124. X        }
  125. X        putchar('\n');
  126. X        }
  127. X    }
  128. X    }
  129. X    if (debug & 8)
  130. X    dump(root);
  131. X#endif
  132. X
  133. X    /* first pass to look for numeric variables */
  134. X
  135. X    prewalk(0,0,root,&i);
  136. X
  137. X    /* second pass to produce new program */
  138. X
  139. X    tmpstr = walk(0,0,root,&i);
  140. X    str = str_make("#!/bin/perl\n\n");
  141. X    if (do_opens && opens) {
  142. X    str_scat(str,opens);
  143. X    str_free(opens);
  144. X    str_cat(str,"\n");
  145. X    }
  146. X    str_scat(str,tmpstr);
  147. X    str_free(tmpstr);
  148. X#ifdef DEBUGGING
  149. X    if (!(debug & 16))
  150. X#endif
  151. X    fixup(str);
  152. X    putlines(str);
  153. X    exit(0);
  154. X}
  155. X
  156. X#define RETURN(retval) return (bufptr = s,retval)
  157. X#define XTERM(retval) return (expectterm = TRUE,bufptr = s,retval)
  158. X#define XOP(retval) return (expectterm = FALSE,bufptr = s,retval)
  159. X#define ID(x) return (yylval=string(x,0),expectterm = FALSE,bufptr = s,VAR)
  160. X
  161. Xyylex()
  162. X{
  163. X    register char *s = bufptr;
  164. X    register char *d;
  165. X    register int tmp;
  166. X
  167. X  retry:
  168. X#ifdef YYDEBUG
  169. X    if (yydebug)
  170. X    if (index(s,'\n'))
  171. X        fprintf(stderr,"Tokener at %s",s);
  172. X    else
  173. X        fprintf(stderr,"Tokener at %s\n",s);
  174. X#endif
  175. X    switch (*s) {
  176. X    default:
  177. X    fprintf(stderr,
  178. X        "Unrecognized character %c in file %s line %d--ignoring.\n",
  179. X         *s++,filename,line);
  180. X    goto retry;
  181. X    case '\\':
  182. X    case 0:
  183. X    s = str_get(linestr);
  184. X    *s = '\0';
  185. X    if (!rsfp)
  186. X        RETURN(0);
  187. X    line++;
  188. X    if ((s = str_gets(linestr, rsfp)) == Nullch) {
  189. X        if (rsfp != stdin)
  190. X        fclose(rsfp);
  191. X        rsfp = Nullfp;
  192. X        s = str_get(linestr);
  193. X        RETURN(0);
  194. X    }
  195. X    goto retry;
  196. X    case ' ': case '\t':
  197. X    s++;
  198. X    goto retry;
  199. X    case '\n':
  200. X    *s = '\0';
  201. X    XTERM(NEWLINE);
  202. X    case '#':
  203. X    yylval = string(s,0);
  204. X    *s = '\0';
  205. X    XTERM(COMMENT);
  206. X    case ';':
  207. X    tmp = *s++;
  208. X    if (*s == '\n') {
  209. X        s++;
  210. X        XTERM(SEMINEW);
  211. X    }
  212. X    XTERM(tmp);
  213. X    case '(':
  214. X    case '{':
  215. X    case '[':
  216. X    case ')':
  217. X    case ']':
  218. X    tmp = *s++;
  219. X    XOP(tmp);
  220. X    case 127:
  221. X    s++;
  222. X    XTERM('}');
  223. X    case '}':
  224. X    for (d = s + 1; isspace(*d); d++) ;
  225. X    if (!*d)
  226. X        s = d - 1;
  227. X    *s = 127;
  228. X    XTERM(';');
  229. X    case ',':
  230. X    tmp = *s++;
  231. X    XTERM(tmp);
  232. X    case '~':
  233. X    s++;
  234. X    XTERM(MATCHOP);
  235. X    case '+':
  236. X    case '-':
  237. X    if (s[1] == *s) {
  238. X        s++;
  239. X        if (*s++ == '+')
  240. X        XTERM(INCR);
  241. X        else
  242. X        XTERM(DECR);
  243. X    }
  244. X    /* FALL THROUGH */
  245. X    case '*':
  246. X    case '%':
  247. X    tmp = *s++;
  248. X    if (*s == '=') {
  249. X        yylval = string(s-1,2);
  250. X        s++;
  251. X        XTERM(ASGNOP);
  252. X    }
  253. X    XTERM(tmp);
  254. X    case '&':
  255. X    s++;
  256. X    tmp = *s++;
  257. X    if (tmp == '&')
  258. X        XTERM(ANDAND);
  259. X    s--;
  260. X    XTERM('&');
  261. X    case '|':
  262. X    s++;
  263. X    tmp = *s++;
  264. X    if (tmp == '|')
  265. X        XTERM(OROR);
  266. X    s--;
  267. X    XTERM('|');
  268. X    case '=':
  269. X    s++;
  270. X    tmp = *s++;
  271. X    if (tmp == '=') {
  272. X        yylval = string("==",2);
  273. X        XTERM(RELOP);
  274. X    }
  275. X    s--;
  276. X    yylval = string("=",1);
  277. X    XTERM(ASGNOP);
  278. X    case '!':
  279. X    s++;
  280. X    tmp = *s++;
  281. X    if (tmp == '=') {
  282. X        yylval = string("!=",2);
  283. X        XTERM(RELOP);
  284. X    }
  285. X    if (tmp == '~') {
  286. X        yylval = string("!~",2);
  287. X        XTERM(MATCHOP);
  288. X    }
  289. X    s--;
  290. X    XTERM(NOT);
  291. X    case '<':
  292. X    s++;
  293. X    tmp = *s++;
  294. X    if (tmp == '=') {
  295. X        yylval = string("<=",2);
  296. X        XTERM(RELOP);
  297. X    }
  298. X    s--;
  299. X    yylval = string("<",1);
  300. X    XTERM(RELOP);
  301. X    case '>':
  302. X    s++;
  303. X    tmp = *s++;
  304. X    if (tmp == '=') {
  305. X        yylval = string(">=",2);
  306. X        XTERM(RELOP);
  307. X    }
  308. X    s--;
  309. X    yylval = string(">",1);
  310. X    XTERM(RELOP);
  311. X
  312. X#define SNARFWORD \
  313. X    d = tokenbuf; \
  314. X    while (isalpha(*s) || isdigit(*s) || *s == '_') \
  315. X        *d++ = *s++; \
  316. X    *d = '\0'; \
  317. X    d = tokenbuf;
  318. X
  319. X    case '$':
  320. X    s++;
  321. X    if (*s == '0') {
  322. X        s++;
  323. X        do_chop = TRUE;
  324. X        need_entire = TRUE;
  325. X        ID("0");
  326. X    }
  327. X    do_split = TRUE;
  328. X    if (isdigit(*s)) {
  329. X        for (d = s; isdigit(*s); s++) ;
  330. X        yylval = string(d,s-d);
  331. X        tmp = atoi(d);
  332. X        if (tmp > maxfld)
  333. X        maxfld = tmp;
  334. X        XOP(FIELD);
  335. X    }
  336. X    split_to_array = set_array_base = TRUE;
  337. X    XOP(VFIELD);
  338. X
  339. X    case '/':            /* may either be division or pattern */
  340. X    if (expectterm) {
  341. X        s = scanpat(s);
  342. X        XTERM(REGEX);
  343. X    }
  344. X    tmp = *s++;
  345. X    if (*s == '=') {
  346. X        yylval = string("/=",2);
  347. X        s++;
  348. X        XTERM(ASGNOP);
  349. X    }
  350. X    XTERM(tmp);
  351. X
  352. X    case '0': case '1': case '2': case '3': case '4':
  353. X    case '5': case '6': case '7': case '8': case '9':
  354. X    s = scannum(s);
  355. X    XOP(NUMBER);
  356. X    case '"':
  357. X    s++;
  358. X    s = cpy2(tokenbuf,s,s[-1]);
  359. X    if (!*s)
  360. X        fatal("String not terminated:\n%s",str_get(linestr));
  361. X    s++;
  362. X    yylval = string(tokenbuf,0);
  363. X    XOP(STRING);
  364. X
  365. X    case 'a': case 'A':
  366. X    SNARFWORD;
  367. X    ID(d);
  368. X    case 'b': case 'B':
  369. X    SNARFWORD;
  370. X    if (strEQ(d,"break"))
  371. X        XTERM(BREAK);
  372. X    if (strEQ(d,"BEGIN"))
  373. X        XTERM(BEGIN);
  374. X    ID(d);
  375. X    case 'c': case 'C':
  376. X    SNARFWORD;
  377. X    if (strEQ(d,"continue"))
  378. X        XTERM(CONTINUE);
  379. X    ID(d);
  380. X    case 'd': case 'D':
  381. X    SNARFWORD;
  382. X    ID(d);
  383. X    case 'e': case 'E':
  384. X    SNARFWORD;
  385. X    if (strEQ(d,"END"))
  386. X        XTERM(END);
  387. X    if (strEQ(d,"else"))
  388. X        XTERM(ELSE);
  389. X    if (strEQ(d,"exit")) {
  390. X        saw_line_op = TRUE;
  391. X        XTERM(EXIT);
  392. X    }
  393. X    if (strEQ(d,"exp")) {
  394. X        yylval = OEXP;
  395. X        XTERM(FUN1);
  396. X    }
  397. X    ID(d);
  398. X    case 'f': case 'F':
  399. X    SNARFWORD;
  400. X    if (strEQ(d,"FS")) {
  401. X        saw_FS++;
  402. X        if (saw_FS == 1 && in_begin) {
  403. X        for (d = s; *d && isspace(*d); d++) ;
  404. X        if (*d == '=') {
  405. X            for (d++; *d && isspace(*d); d++) ;
  406. X            if (*d == '"' && d[2] == '"')
  407. X            const_FS = d[1];
  408. X        }
  409. X        }
  410. X        ID(tokenbuf);
  411. X    }
  412. X    if (strEQ(d,"FILENAME"))
  413. X        d = "ARGV";
  414. X    if (strEQ(d,"for"))
  415. X        XTERM(FOR);
  416. X    ID(d);
  417. X    case 'g': case 'G':
  418. X    SNARFWORD;
  419. X    if (strEQ(d,"getline"))
  420. X        XTERM(GETLINE);
  421. X    ID(d);
  422. X    case 'h': case 'H':
  423. X    SNARFWORD;
  424. X    ID(d);
  425. X    case 'i': case 'I':
  426. X    SNARFWORD;
  427. X    if (strEQ(d,"if"))
  428. X        XTERM(IF);
  429. X    if (strEQ(d,"in"))
  430. X        XTERM(IN);
  431. X    if (strEQ(d,"index")) {
  432. X        set_array_base = TRUE;
  433. X        XTERM(INDEX);
  434. X    }
  435. X    if (strEQ(d,"int")) {
  436. X        yylval = OINT;
  437. X        XTERM(FUN1);
  438. X    }
  439. X    ID(d);
  440. X    case 'j': case 'J':
  441. X    SNARFWORD;
  442. X    ID(d);
  443. X    case 'k': case 'K':
  444. X    SNARFWORD;
  445. X    ID(d);
  446. X    case 'l': case 'L':
  447. X    SNARFWORD;
  448. X    if (strEQ(d,"length")) {
  449. X        yylval = OLENGTH;
  450. X        XTERM(FUN1);
  451. X    }
  452. X    if (strEQ(d,"log")) {
  453. X        yylval = OLOG;
  454. X        XTERM(FUN1);
  455. X    }
  456. X    ID(d);
  457. X    case 'm': case 'M':
  458. X    SNARFWORD;
  459. X    ID(d);
  460. X    case 'n': case 'N':
  461. X    SNARFWORD;
  462. X    if (strEQ(d,"NF"))
  463. X        do_split = split_to_array = set_array_base = TRUE;
  464. X    if (strEQ(d,"next")) {
  465. X        saw_line_op = TRUE;
  466. X        XTERM(NEXT);
  467. X    }
  468. X    ID(d);
  469. X    case 'o': case 'O':
  470. X    SNARFWORD;
  471. X    if (strEQ(d,"ORS")) {
  472. X        saw_ORS = TRUE;
  473. X        d = "$\\";
  474. X    }
  475. X    if (strEQ(d,"OFS")) {
  476. X        saw_OFS = TRUE;
  477. X        d = "$,";
  478. X    }
  479. X    if (strEQ(d,"OFMT")) {
  480. X        d = "$#";
  481. X    }
  482. X    ID(d);
  483. X    case 'p': case 'P':
  484. X    SNARFWORD;
  485. X    if (strEQ(d,"print")) {
  486. X        XTERM(PRINT);
  487. X    }
  488. X    if (strEQ(d,"printf")) {
  489. X        XTERM(PRINTF);
  490. X    }
  491. X    ID(d);
  492. X    case 'q': case 'Q':
  493. X    SNARFWORD;
  494. X    ID(d);
  495. X    case 'r': case 'R':
  496. X    SNARFWORD;
  497. X    if (strEQ(d,"RS")) {
  498. X        d = "$/";
  499. X        saw_RS = TRUE;
  500. X    }
  501. X    ID(d);
  502. X    case 's': case 'S':
  503. X    SNARFWORD;
  504. X    if (strEQ(d,"split")) {
  505. X        set_array_base = TRUE;
  506. X        XOP(SPLIT);
  507. X    }
  508. X    if (strEQ(d,"substr")) {
  509. X        set_array_base = TRUE;
  510. X        XTERM(SUBSTR);
  511. X    }
  512. X    if (strEQ(d,"sprintf"))
  513. X        XTERM(SPRINTF);
  514. X    if (strEQ(d,"sqrt")) {
  515. X        yylval = OSQRT;
  516. X        XTERM(FUN1);
  517. X    }
  518. X    ID(d);
  519. X    case 't': case 'T':
  520. X    SNARFWORD;
  521. X    ID(d);
  522. X    case 'u': case 'U':
  523. X    SNARFWORD;
  524. X    ID(d);
  525. X    case 'v': case 'V':
  526. X    SNARFWORD;
  527. X    ID(d);
  528. X    case 'w': case 'W':
  529. X    SNARFWORD;
  530. X    if (strEQ(d,"while"))
  531. X        XTERM(WHILE);
  532. X    ID(d);
  533. X    case 'x': case 'X':
  534. X    SNARFWORD;
  535. X    ID(d);
  536. X    case 'y': case 'Y':
  537. X    SNARFWORD;
  538. X    ID(d);
  539. X    case 'z': case 'Z':
  540. X    SNARFWORD;
  541. X    ID(d);
  542. X    }
  543. X}
  544. X
  545. Xchar *
  546. Xscanpat(s)
  547. Xregister char *s;
  548. X{
  549. X    register char *d;
  550. X
  551. X    switch (*s++) {
  552. X    case '/':
  553. X    break;
  554. X    default:
  555. X    fatal("Search pattern not found:\n%s",str_get(linestr));
  556. X    }
  557. X    s = cpytill(tokenbuf,s,s[-1]);
  558. X    if (!*s)
  559. X    fatal("Search pattern not terminated:\n%s",str_get(linestr));
  560. X    s++;
  561. X    yylval = string(tokenbuf,0);
  562. X    return s;
  563. X}
  564. X
  565. Xyyerror(s)
  566. Xchar *s;
  567. X{
  568. X    fprintf(stderr,"%s in file %s at line %d\n",
  569. X      s,filename,line);
  570. X}
  571. X
  572. Xchar *
  573. Xscannum(s)
  574. Xregister char *s;
  575. X{
  576. X    register char *d;
  577. X
  578. X    switch (*s) {
  579. X    case '1': case '2': case '3': case '4': case '5':
  580. X    case '6': case '7': case '8': case '9': case '0' : case '.':
  581. X    d = tokenbuf;
  582. X    while (isdigit(*s) || *s == '_')
  583. X        *d++ = *s++;
  584. X    if (*s == '.' && index("0123456789eE",s[1]))
  585. X        *d++ = *s++;
  586. X    while (isdigit(*s) || *s == '_')
  587. X        *d++ = *s++;
  588. X    if (index("eE",*s) && index("+-0123456789",s[1]))
  589. X        *d++ = *s++;
  590. X    if (*s == '+' || *s == '-')
  591. X        *d++ = *s++;
  592. X    while (isdigit(*s))
  593. X        *d++ = *s++;
  594. X    *d = '\0';
  595. X    yylval = string(tokenbuf,0);
  596. X    break;
  597. X    }
  598. X    return s;
  599. X}
  600. X
  601. Xstring(ptr,len)
  602. Xchar *ptr;
  603. X{
  604. X    int retval = mop;
  605. X
  606. X    ops[mop++].ival = OSTRING + (1<<8);
  607. X    if (!len)
  608. X    len = strlen(ptr);
  609. X    ops[mop].cval = safemalloc(len+1);
  610. X    strncpy(ops[mop].cval,ptr,len);
  611. X    ops[mop++].cval[len] = '\0';
  612. X    return retval;
  613. X}
  614. X
  615. Xoper0(type)
  616. Xint type;
  617. X{
  618. X    int retval = mop;
  619. X
  620. X    if (type > 255)
  621. X    fatal("type > 255 (%d)\n",type);
  622. X    ops[mop++].ival = type;
  623. X    return retval;
  624. X}
  625. X
  626. Xoper1(type,arg1)
  627. Xint type;
  628. Xint arg1;
  629. X{
  630. X    int retval = mop;
  631. X
  632. X    if (type > 255)
  633. X    fatal("type > 255 (%d)\n",type);
  634. X    ops[mop++].ival = type + (1<<8);
  635. X    ops[mop++].ival = arg1;
  636. X    return retval;
  637. X}
  638. X
  639. Xoper2(type,arg1,arg2)
  640. Xint type;
  641. Xint arg1;
  642. Xint arg2;
  643. X{
  644. X    int retval = mop;
  645. X
  646. X    if (type > 255)
  647. X    fatal("type > 255 (%d)\n",type);
  648. X    ops[mop++].ival = type + (2<<8);
  649. X    ops[mop++].ival = arg1;
  650. X    ops[mop++].ival = arg2;
  651. X    return retval;
  652. X}
  653. X
  654. Xoper3(type,arg1,arg2,arg3)
  655. Xint type;
  656. Xint arg1;
  657. Xint arg2;
  658. Xint arg3;
  659. X{
  660. X    int retval = mop;
  661. X
  662. X    if (type > 255)
  663. X    fatal("type > 255 (%d)\n",type);
  664. X    ops[mop++].ival = type + (3<<8);
  665. X    ops[mop++].ival = arg1;
  666. X    ops[mop++].ival = arg2;
  667. X    ops[mop++].ival = arg3;
  668. X    return retval;
  669. X}
  670. X
  671. Xoper4(type,arg1,arg2,arg3,arg4)
  672. Xint type;
  673. Xint arg1;
  674. Xint arg2;
  675. Xint arg3;
  676. Xint arg4;
  677. X{
  678. X    int retval = mop;
  679. X
  680. X    if (type > 255)
  681. X    fatal("type > 255 (%d)\n",type);
  682. X    ops[mop++].ival = type + (4<<8);
  683. X    ops[mop++].ival = arg1;
  684. X    ops[mop++].ival = arg2;
  685. X    ops[mop++].ival = arg3;
  686. X    ops[mop++].ival = arg4;
  687. X    return retval;
  688. X}
  689. X
  690. Xoper5(type,arg1,arg2,arg3,arg4,arg5)
  691. Xint type;
  692. Xint arg1;
  693. Xint arg2;
  694. Xint arg3;
  695. Xint arg4;
  696. Xint arg5;
  697. X{
  698. X    int retval = mop;
  699. X
  700. X    if (type > 255)
  701. X    fatal("type > 255 (%d)\n",type);
  702. X    ops[mop++].ival = type + (5<<8);
  703. X    ops[mop++].ival = arg1;
  704. X    ops[mop++].ival = arg2;
  705. X    ops[mop++].ival = arg3;
  706. X    ops[mop++].ival = arg4;
  707. X    ops[mop++].ival = arg5;
  708. X    return retval;
  709. X}
  710. X
  711. Xint depth = 0;
  712. X
  713. Xdump(branch)
  714. Xint branch;
  715. X{
  716. X    register int type;
  717. X    register int len;
  718. X    register int i;
  719. X
  720. X    type = ops[branch].ival;
  721. X    len = type >> 8;
  722. X    type &= 255;
  723. X    for (i=depth; i; i--)
  724. X    printf(" ");
  725. X    if (type == OSTRING) {
  726. X    printf("%-5d\"%s\"\n",branch,ops[branch+1].cval);
  727. X    }
  728. X    else {
  729. X    printf("(%-5d%s %d\n",branch,opname[type],len);
  730. X    depth++;
  731. X    for (i=1; i<=len; i++)
  732. X        dump(ops[branch+i].ival);
  733. X    depth--;
  734. X    for (i=depth; i; i--)
  735. X        printf(" ");
  736. X    printf(")\n");
  737. X    }
  738. X}
  739. X
  740. Xbl(arg,maybe)
  741. Xint arg;
  742. Xint maybe;
  743. X{
  744. X    if (!arg)
  745. X    return 0;
  746. X    else if ((ops[arg].ival & 255) != OBLOCK)
  747. X    return oper2(OBLOCK,arg,maybe);
  748. X    else if ((ops[arg].ival >> 8) != 2)
  749. X    return oper2(OBLOCK,ops[arg+1].ival,maybe);
  750. X    else
  751. X    return arg;
  752. X}
  753. X
  754. Xfixup(str)
  755. XSTR *str;
  756. X{
  757. X    register char *s;
  758. X    register char *t;
  759. X
  760. X    for (s = str->str_ptr; *s; s++) {
  761. X    if (*s == ';' && s[1] == ' ' && s[2] == '\n') {
  762. X        strcpy(s+1,s+2);
  763. X        s++;
  764. X    }
  765. X    else if (*s == '\n') {
  766. X        for (t = s+1; isspace(*t & 127); t++) ;
  767. X        t--;
  768. X        while (isspace(*t & 127) && *t != '\n') t--;
  769. X        if (*t == '\n' && t-s > 1) {
  770. X        if (s[-1] == '{')
  771. X            s--;
  772. X        strcpy(s+1,t);
  773. X        }
  774. X        s++;
  775. X    }
  776. X    }
  777. X}
  778. X
  779. Xputlines(str)
  780. XSTR *str;
  781. X{
  782. X    register char *d, *s, *t, *e;
  783. X    register int pos, newpos;
  784. X
  785. X    d = tokenbuf;
  786. X    pos = 0;
  787. X    for (s = str->str_ptr; *s; s++) {
  788. X    *d++ = *s;
  789. X    pos++;
  790. X    if (*s == '\n') {
  791. X        *d = '\0';
  792. X        d = tokenbuf;
  793. X        pos = 0;
  794. X        putone();
  795. X    }
  796. X    else if (*s == '\t')
  797. X        pos += 7;
  798. X    if (pos > 78) {        /* split a long line? */
  799. X        *d-- = '\0';
  800. X        newpos = 0;
  801. X        for (t = tokenbuf; isspace(*t & 127); t++) {
  802. X        if (*t == '\t')
  803. X            newpos += 8;
  804. X        else
  805. X            newpos += 1;
  806. X        }
  807. X        e = d;
  808. X        while (d > tokenbuf && (*d != ' ' || d[-1] != ';'))
  809. X        d--;
  810. X        if (d < t+10) {
  811. X        d = e;
  812. X        while (d > tokenbuf &&
  813. X          (*d != ' ' || d[-1] != '|' || d[-2] != '|') )
  814. X            d--;
  815. X        }
  816. X        if (d < t+10) {
  817. X        d = e;
  818. X        while (d > tokenbuf &&
  819. X          (*d != ' ' || d[-1] != '&' || d[-2] != '&') )
  820. X            d--;
  821. X        }
  822. X        if (d < t+10) {
  823. X        d = e;
  824. X        while (d > tokenbuf && (*d != ' ' || d[-1] != ','))
  825. X            d--;
  826. X        }
  827. X        if (d < t+10) {
  828. X        d = e;
  829. X        while (d > tokenbuf && *d != ' ')
  830. X            d--;
  831. X        }
  832. X        if (d > t+3) {
  833. X        *d = '\0';
  834. X        putone();
  835. X        putchar('\n');
  836. X        if (d[-1] != ';' && !(newpos % 4)) {
  837. X            *t++ = ' ';
  838. X            *t++ = ' ';
  839. X            newpos += 2;
  840. X        }
  841. X        strcpy(t,d+1);
  842. X        newpos += strlen(t);
  843. X        d = t + strlen(t);
  844. X        pos = newpos;
  845. X        }
  846. X        else
  847. X        d = e + 1;
  848. X    }
  849. X    }
  850. X}
  851. X
  852. Xputone()
  853. X{
  854. X    register char *t;
  855. X
  856. X    for (t = tokenbuf; *t; t++) {
  857. X    *t &= 127;
  858. X    if (*t == 127) {
  859. X        *t = ' ';
  860. X        strcpy(t+strlen(t)-1, "\t#???\n");
  861. X    }
  862. X    }
  863. X    t = tokenbuf;
  864. X    if (*t == '#') {
  865. X    if (strnEQ(t,"#!/bin/awk",10) || strnEQ(t,"#! /bin/awk",11))
  866. X        return;
  867. X    }
  868. X    fputs(tokenbuf,stdout);
  869. X}
  870. X
  871. Xnumary(arg)
  872. Xint arg;
  873. X{
  874. X    STR *key;
  875. X    int dummy;
  876. X
  877. X    key = walk(0,0,arg,&dummy);
  878. X    str_cat(key,"[]");
  879. X    hstore(symtab,key->str_ptr,str_make("1"));
  880. X    str_free(key);
  881. X    set_array_base = TRUE;
  882. X    return arg;
  883. X}
  884. !STUFFY!FUNK!
  885. echo Extracting cmd.c
  886. sed >cmd.c <<'!STUFFY!FUNK!' -e 's/X//'
  887. X/* $Header: cmd.c,v 1.0 87/12/18 13:04:51 root Exp $
  888. X *
  889. X * $Log:    cmd.c,v $
  890. X * Revision 1.0  87/12/18  13:04:51  root
  891. X * Initial revision
  892. X * 
  893. X */
  894. X
  895. X#include "handy.h"
  896. X#include "EXTERN.h"
  897. X#include "search.h"
  898. X#include "util.h"
  899. X#include "perl.h"
  900. X
  901. Xstatic STR str_chop;
  902. X
  903. X/* This is the main command loop.  We try to spend as much time in this loop
  904. X * as possible, so lots of optimizations do their activities in here.  This
  905. X * means things get a little sloppy.
  906. X */
  907. X
  908. XSTR *
  909. Xcmd_exec(cmd)
  910. Xregister CMD *cmd;
  911. X{
  912. X    SPAT *oldspat;
  913. X#ifdef DEBUGGING
  914. X    int olddlevel;
  915. X    int entdlevel;
  916. X#endif
  917. X    register STR *retstr;
  918. X    register char *tmps;
  919. X    register int cmdflags;
  920. X    register bool match;
  921. X    register char *go_to = goto_targ;
  922. X    ARG *arg;
  923. X    FILE *fp;
  924. X
  925. X    retstr = &str_no;
  926. X#ifdef DEBUGGING
  927. X    entdlevel = dlevel;
  928. X#endif
  929. Xtail_recursion_entry:
  930. X#ifdef DEBUGGING
  931. X    dlevel = entdlevel;
  932. X#endif
  933. X    if (cmd == Nullcmd)
  934. X    return retstr;
  935. X    cmdflags = cmd->c_flags;    /* hopefully load register */
  936. X    if (go_to) {
  937. X    if (cmd->c_label && strEQ(go_to,cmd->c_label))
  938. X        goto_targ = go_to = Nullch;        /* here at last */
  939. X    else {
  940. X        switch (cmd->c_type) {
  941. X        case C_IF:
  942. X        oldspat = curspat;
  943. X#ifdef DEBUGGING
  944. X        olddlevel = dlevel;
  945. X#endif
  946. X        retstr = &str_yes;
  947. X        if (cmd->ucmd.ccmd.cc_true) {
  948. X#ifdef DEBUGGING
  949. X            debname[dlevel] = 't';
  950. X            debdelim[dlevel++] = '_';
  951. X#endif
  952. X            retstr = cmd_exec(cmd->ucmd.ccmd.cc_true);
  953. X        }
  954. X        if (!goto_targ) {
  955. X            go_to = Nullch;
  956. X        } else {
  957. X            retstr = &str_no;
  958. X            if (cmd->ucmd.ccmd.cc_alt) {
  959. X#ifdef DEBUGGING
  960. X            debname[dlevel] = 'e';
  961. X            debdelim[dlevel++] = '_';
  962. X#endif
  963. X            retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt);
  964. X            }
  965. X        }
  966. X        if (!goto_targ)
  967. X            go_to = Nullch;
  968. X        curspat = oldspat;
  969. X#ifdef DEBUGGING
  970. X        dlevel = olddlevel;
  971. X#endif
  972. X        break;
  973. X        case C_BLOCK:
  974. X        case C_WHILE:
  975. X        if (!(cmdflags & CF_ONCE)) {
  976. X            cmdflags |= CF_ONCE;
  977. X            loop_ptr++;
  978. X            loop_stack[loop_ptr].loop_label = cmd->c_label;
  979. X#ifdef DEBUGGING
  980. X            if (debug & 4) {
  981. X            deb("(Pushing label #%d %s)\n",
  982. X              loop_ptr,cmd->c_label);
  983. X            }
  984. X#endif
  985. X        }
  986. X        switch (setjmp(loop_stack[loop_ptr].loop_env)) {
  987. X        case O_LAST:    /* not done unless go_to found */
  988. X            go_to = Nullch;
  989. X            retstr = &str_no;
  990. X#ifdef DEBUGGING
  991. X            olddlevel = dlevel;
  992. X#endif
  993. X            curspat = oldspat;
  994. X#ifdef DEBUGGING
  995. X            if (debug & 4) {
  996. X            deb("(Popping label #%d %s)\n",loop_ptr,
  997. X                loop_stack[loop_ptr].loop_label);
  998. X            }
  999. X#endif
  1000. X            loop_ptr--;
  1001. X            cmd = cmd->c_next;
  1002. X            goto tail_recursion_entry;
  1003. X        case O_NEXT:    /* not done unless go_to found */
  1004. X            go_to = Nullch;
  1005. X            goto next_iter;
  1006. X        case O_REDO:    /* not done unless go_to found */
  1007. X            go_to = Nullch;
  1008. X            goto doit;
  1009. X        }
  1010. X        oldspat = curspat;
  1011. X#ifdef DEBUGGING
  1012. X        olddlevel = dlevel;
  1013. X#endif
  1014. X        if (cmd->ucmd.ccmd.cc_true) {
  1015. X#ifdef DEBUGGING
  1016. X            debname[dlevel] = 't';
  1017. X            debdelim[dlevel++] = '_';
  1018. X#endif
  1019. X            cmd_exec(cmd->ucmd.ccmd.cc_true);
  1020. X        }
  1021. X        if (!goto_targ) {
  1022. X            go_to = Nullch;
  1023. X            goto next_iter;
  1024. X        }
  1025. X#ifdef DEBUGGING
  1026. X        dlevel = olddlevel;
  1027. X#endif
  1028. X        if (cmd->ucmd.ccmd.cc_alt) {
  1029. X#ifdef DEBUGGING
  1030. X            debname[dlevel] = 'a';
  1031. X            debdelim[dlevel++] = '_';
  1032. X#endif
  1033. X            cmd_exec(cmd->ucmd.ccmd.cc_alt);
  1034. X        }
  1035. X        if (goto_targ)
  1036. X            break;
  1037. X        go_to = Nullch;
  1038. X        goto finish_while;
  1039. X        }
  1040. X        cmd = cmd->c_next;
  1041. X        if (cmd && cmd->c_head == cmd)    /* reached end of while loop */
  1042. X        return retstr;        /* targ isn't in this block */
  1043. X        goto tail_recursion_entry;
  1044. X    }
  1045. X    }
  1046. X
  1047. Xuntil_loop:
  1048. X
  1049. X#ifdef DEBUGGING
  1050. X    if (debug & 2) {
  1051. X    deb("%s    (%lx)    r%lx    t%lx    a%lx    n%lx    cs%lx\n",
  1052. X        cmdname[cmd->c_type],cmd,cmd->c_expr,
  1053. X        cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,curspat);
  1054. X    }
  1055. X    debname[dlevel] = cmdname[cmd->c_type][0];
  1056. X    debdelim[dlevel++] = '!';
  1057. X#endif
  1058. X    while (tmps_max >= 0)        /* clean up after last eval */
  1059. X    str_free(tmps_list[tmps_max--]);
  1060. X
  1061. X    /* Here is some common optimization */
  1062. X
  1063. X    if (cmdflags & CF_COND) {
  1064. X    switch (cmdflags & CF_OPTIMIZE) {
  1065. X
  1066. X    case CFT_FALSE:
  1067. X        retstr = cmd->c_first;
  1068. X        match = FALSE;
  1069. X        if (cmdflags & CF_NESURE)
  1070. X        goto maybe;
  1071. X        break;
  1072. X    case CFT_TRUE:
  1073. X        retstr = cmd->c_first;
  1074. X        match = TRUE;
  1075. X        if (cmdflags & CF_EQSURE)
  1076. X        goto flipmaybe;
  1077. X        break;
  1078. X
  1079. X    case CFT_REG:
  1080. X        retstr = STAB_STR(cmd->c_stab);
  1081. X        match = str_true(retstr);    /* => retstr = retstr, c2 should fix */
  1082. X        if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
  1083. X        goto flipmaybe;
  1084. X        break;
  1085. X
  1086. X    case CFT_ANCHOR:    /* /^pat/ optimization */
  1087. X        if (multiline) {
  1088. X        if (*cmd->c_first->str_ptr && !(cmdflags & CF_EQSURE))
  1089. X            goto scanner;    /* just unanchor it */
  1090. X        else
  1091. X            break;        /* must evaluate */
  1092. X        }
  1093. X        /* FALL THROUGH */
  1094. X    case CFT_STROP:        /* string op optimization */
  1095. X        retstr = STAB_STR(cmd->c_stab);
  1096. X        if (*cmd->c_first->str_ptr == *str_get(retstr) &&
  1097. X            strnEQ(cmd->c_first->str_ptr, str_get(retstr),
  1098. X              cmd->c_flen) ) {
  1099. X        if (cmdflags & CF_EQSURE) {
  1100. X            match = !(cmdflags & CF_FIRSTNEG);
  1101. X            retstr = &str_yes;
  1102. X            goto flipmaybe;
  1103. X        }
  1104. X        }
  1105. X        else if (cmdflags & CF_NESURE) {
  1106. X        match = cmdflags & CF_FIRSTNEG;
  1107. X        retstr = &str_no;
  1108. X        goto flipmaybe;
  1109. X        }
  1110. X        break;            /* must evaluate */
  1111. X
  1112. X    case CFT_SCAN:            /* non-anchored search */
  1113. X      scanner:
  1114. X        retstr = STAB_STR(cmd->c_stab);
  1115. X        if (instr(str_get(retstr),cmd->c_first->str_ptr)) {
  1116. X        if (cmdflags & CF_EQSURE) {
  1117. X            match = !(cmdflags & CF_FIRSTNEG);
  1118. X            retstr = &str_yes;
  1119. X            goto flipmaybe;
  1120. X        }
  1121. X        }
  1122. X        else if (cmdflags & CF_NESURE) {
  1123. X        match = cmdflags & CF_FIRSTNEG;
  1124. X        retstr = &str_no;
  1125. X        goto flipmaybe;
  1126. X        }
  1127. X        break;            /* must evaluate */
  1128. X
  1129. X    case CFT_GETS:            /* really a while (<file>) */
  1130. X        last_in_stab = cmd->c_stab;
  1131. X        fp = last_in_stab->stab_io->fp;
  1132. X        retstr = defstab->stab_val;
  1133. X        if (fp && str_gets(retstr, fp)) {
  1134. X        last_in_stab->stab_io->lines++;
  1135. X        match = TRUE;
  1136. X        }
  1137. X        else if (last_in_stab->stab_io->flags & IOF_ARGV)
  1138. X        goto doeval;    /* doesn't necessarily count as EOF yet */
  1139. X        else {
  1140. X        retstr = &str_no;
  1141. X        match = FALSE;
  1142. X        }
  1143. X        goto flipmaybe;
  1144. X    case CFT_EVAL:
  1145. X        break;
  1146. X    case CFT_UNFLIP:
  1147. X        retstr = eval(cmd->c_expr,Null(char***));
  1148. X        match = str_true(retstr);
  1149. X        if (cmd->c_expr->arg_type == O_FLIP)    /* undid itself? */
  1150. X        cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  1151. X        goto maybe;
  1152. X    case CFT_CHOP:
  1153. X        retstr = cmd->c_stab->stab_val;
  1154. X        match = (retstr->str_cur != 0);
  1155. X        tmps = str_get(retstr);
  1156. X        tmps += retstr->str_cur - match;
  1157. X        str_set(&str_chop,tmps);
  1158. X        *tmps = '\0';
  1159. X        retstr->str_nok = 0;
  1160. X        retstr->str_cur = tmps - retstr->str_ptr;
  1161. X        retstr = &str_chop;
  1162. X        goto flipmaybe;
  1163. X    }
  1164. X
  1165. X    /* we have tried to make this normal case as abnormal as possible */
  1166. X
  1167. X    doeval:
  1168. X    retstr = eval(cmd->c_expr,Null(char***));
  1169. X    match = str_true(retstr);
  1170. X    goto maybe;
  1171. X
  1172. X    /* if flipflop was true, flop it */
  1173. X
  1174. X    flipmaybe:
  1175. X    if (match && cmdflags & CF_FLIP) {
  1176. X        if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  1177. X        retstr = eval(cmd->c_expr,Null(char***)); /* let eval undo it */
  1178. X        cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  1179. X        }
  1180. X        else {
  1181. X        retstr = eval(cmd->c_expr,Null(char***)); /* let eval do it */
  1182. X        if (cmd->c_expr->arg_type == O_FLOP)    /* still toggled? */
  1183. X            cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
  1184. X        }
  1185. X    }
  1186. X    else if (cmdflags & CF_FLIP) {
  1187. X        if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  1188. X        match = TRUE;                /* force on */
  1189. X        }
  1190. X    }
  1191. X
  1192. X    /* at this point, match says whether our expression was true */
  1193. X
  1194. X    maybe:
  1195. X    if (cmdflags & CF_INVERT)
  1196. X        match = !match;
  1197. X    if (!match && cmd->c_type != C_IF) {
  1198. X        cmd = cmd->c_next;
  1199. X        goto tail_recursion_entry;
  1200. X    }
  1201. X    }
  1202. X
  1203. X    /* now to do the actual command, if any */
  1204. X
  1205. X    switch (cmd->c_type) {
  1206. X    case C_NULL:
  1207. X    fatal("panic: cmd_exec\n");
  1208. X    case C_EXPR:            /* evaluated for side effects */
  1209. X    if (cmd->ucmd.acmd.ac_expr) {    /* more to do? */
  1210. X        retstr = eval(cmd->ucmd.acmd.ac_expr,Null(char***));
  1211. X    }
  1212. X    break;
  1213. X    case C_IF:
  1214. X    oldspat = curspat;
  1215. X#ifdef DEBUGGING
  1216. X    olddlevel = dlevel;
  1217. X#endif
  1218. X    if (match) {
  1219. X        retstr = &str_yes;
  1220. X        if (cmd->ucmd.ccmd.cc_true) {
  1221. X#ifdef DEBUGGING
  1222. X        debname[dlevel] = 't';
  1223. X        debdelim[dlevel++] = '_';
  1224. X#endif
  1225. X        retstr = cmd_exec(cmd->ucmd.ccmd.cc_true);
  1226. X        }
  1227. X    }
  1228. X    else {
  1229. X        retstr = &str_no;
  1230. X        if (cmd->ucmd.ccmd.cc_alt) {
  1231. X#ifdef DEBUGGING
  1232. X        debname[dlevel] = 'e';
  1233. X        debdelim[dlevel++] = '_';
  1234. X#endif
  1235. X        retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt);
  1236. X        }
  1237. X    }
  1238. X    curspat = oldspat;
  1239. X#ifdef DEBUGGING
  1240. X    dlevel = olddlevel;
  1241. X#endif
  1242. X    break;
  1243. X    case C_BLOCK:
  1244. X    case C_WHILE:
  1245. X    if (!(cmdflags & CF_ONCE)) {    /* first time through here? */
  1246. X        cmdflags |= CF_ONCE;
  1247. X        loop_ptr++;
  1248. X        loop_stack[loop_ptr].loop_label = cmd->c_label;
  1249. X#ifdef DEBUGGING
  1250. X        if (debug & 4) {
  1251. X        deb("(Pushing label #%d %s)\n",
  1252. X          loop_ptr,cmd->c_label);
  1253. X        }
  1254. X#endif
  1255. X    }
  1256. X    switch (setjmp(loop_stack[loop_ptr].loop_env)) {
  1257. X    case O_LAST:
  1258. X        retstr = &str_no;
  1259. X        curspat = oldspat;
  1260. X#ifdef DEBUGGING
  1261. X        if (debug & 4) {
  1262. X        deb("(Popping label #%d %s)\n",loop_ptr,
  1263. X            loop_stack[loop_ptr].loop_label);
  1264. X        }
  1265. X#endif
  1266. X        loop_ptr--;
  1267. X        cmd = cmd->c_next;
  1268. X        goto tail_recursion_entry;
  1269. X    case O_NEXT:
  1270. X        goto next_iter;
  1271. X    case O_REDO:
  1272. X        goto doit;
  1273. X    }
  1274. X    oldspat = curspat;
  1275. X#ifdef DEBUGGING
  1276. X    olddlevel = dlevel;
  1277. X#endif
  1278. X    doit:
  1279. X    if (cmd->ucmd.ccmd.cc_true) {
  1280. X#ifdef DEBUGGING
  1281. X        debname[dlevel] = 't';
  1282. X        debdelim[dlevel++] = '_';
  1283. X#endif
  1284. X        cmd_exec(cmd->ucmd.ccmd.cc_true);
  1285. X    }
  1286. X    /* actually, this spot is never reached anymore since the above
  1287. X     * cmd_exec() returns through longjmp().  Hooray for structure.
  1288. X     */
  1289. X      next_iter:
  1290. X#ifdef DEBUGGING
  1291. X    dlevel = olddlevel;
  1292. X#endif
  1293. X    if (cmd->ucmd.ccmd.cc_alt) {
  1294. X#ifdef DEBUGGING
  1295. X        debname[dlevel] = 'a';
  1296. X        debdelim[dlevel++] = '_';
  1297. X#endif
  1298. X        cmd_exec(cmd->ucmd.ccmd.cc_alt);
  1299. X    }
  1300. X      finish_while:
  1301. X    curspat = oldspat;
  1302. X#ifdef DEBUGGING
  1303. X    dlevel = olddlevel - 1;
  1304. X#endif
  1305. X    if (cmd->c_type != C_BLOCK)
  1306. X        goto until_loop;    /* go back and evaluate conditional again */
  1307. X    }
  1308. X    if (cmdflags & CF_LOOP) {
  1309. X    cmdflags |= CF_COND;        /* now test the condition */
  1310. X    goto until_loop;
  1311. X    }
  1312. X    cmd = cmd->c_next;
  1313. X    goto tail_recursion_entry;
  1314. X}
  1315. X
  1316. X#ifdef DEBUGGING
  1317. X/*VARARGS1*/
  1318. Xdeb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
  1319. Xchar *pat;
  1320. X{
  1321. X    register int i;
  1322. X
  1323. X    for (i=0; i<dlevel; i++)
  1324. X    fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
  1325. X    fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
  1326. X}
  1327. X#endif
  1328. X
  1329. Xcopyopt(cmd,which)
  1330. Xregister CMD *cmd;
  1331. Xregister CMD *which;
  1332. X{
  1333. X    cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
  1334. X    cmd->c_flags |= which->c_flags;
  1335. X    cmd->c_first = which->c_first;
  1336. X    cmd->c_flen = which->c_flen;
  1337. X    cmd->c_stab = which->c_stab;
  1338. X    return cmd->c_flags;
  1339. X}
  1340. !STUFFY!FUNK!
  1341. echo Extracting x2p/str.c
  1342. sed >x2p/str.c <<'!STUFFY!FUNK!' -e 's/X//'
  1343. X/* $Header: str.c,v 1.0 87/12/18 13:07:26 root Exp $
  1344. X *
  1345. X * $Log:    str.c,v $
  1346. X * Revision 1.0  87/12/18  13:07:26  root
  1347. X * Initial revision
  1348. X * 
  1349. X */
  1350. X
  1351. X#include "handy.h"
  1352. X#include "EXTERN.h"
  1353. X#include "util.h"
  1354. X#include "a2p.h"
  1355. X
  1356. Xstr_numset(str,num)
  1357. Xregister STR *str;
  1358. Xdouble num;
  1359. X{
  1360. X    str->str_nval = num;
  1361. X    str->str_pok = 0;        /* invalidate pointer */
  1362. X    str->str_nok = 1;        /* validate number */
  1363. X}
  1364. X
  1365. Xchar *
  1366. Xstr_2ptr(str)
  1367. Xregister STR *str;
  1368. X{
  1369. X    register char *s;
  1370. X
  1371. X    if (!str)
  1372. X    return "";
  1373. X    GROWSTR(&(str->str_ptr), &(str->str_len), 24);
  1374. X    s = str->str_ptr;
  1375. X    if (str->str_nok) {
  1376. X    sprintf(s,"%.20g",str->str_nval);
  1377. X    while (*s) s++;
  1378. X    }
  1379. X    *s = '\0';
  1380. X    str->str_cur = s - str->str_ptr;
  1381. X    str->str_pok = 1;
  1382. X#ifdef DEBUGGING
  1383. X    if (debug & 32)
  1384. X    fprintf(stderr,"0x%lx ptr(%s)\n",str,str->str_ptr);
  1385. X#endif
  1386. X    return str->str_ptr;
  1387. X}
  1388. X
  1389. Xdouble
  1390. Xstr_2num(str)
  1391. Xregister STR *str;
  1392. X{
  1393. X    if (!str)
  1394. X    return 0.0;
  1395. X    if (str->str_len && str->str_pok)
  1396. X    str->str_nval = atof(str->str_ptr);
  1397. X    else
  1398. X    str->str_nval = 0.0;
  1399. X    str->str_nok = 1;
  1400. X#ifdef DEBUGGING
  1401. X    if (debug & 32)
  1402. X    fprintf(stderr,"0x%lx num(%g)\n",str,str->str_nval);
  1403. X#endif
  1404. X    return str->str_nval;
  1405. X}
  1406. X
  1407. Xstr_sset(dstr,sstr)
  1408. XSTR *dstr;
  1409. Xregister STR *sstr;
  1410. X{
  1411. X    if (!sstr)
  1412. X    str_nset(dstr,No,0);
  1413. X    else if (sstr->str_nok)
  1414. X    str_numset(dstr,sstr->str_nval);
  1415. X    else if (sstr->str_pok)
  1416. X    str_nset(dstr,sstr->str_ptr,sstr->str_cur);
  1417. X    else
  1418. X    str_nset(dstr,"",0);
  1419. X}
  1420. X
  1421. Xstr_nset(str,ptr,len)
  1422. Xregister STR *str;
  1423. Xregister char *ptr;
  1424. Xregister int len;
  1425. X{
  1426. X    GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
  1427. X    bcopy(ptr,str->str_ptr,len);
  1428. X    str->str_cur = len;
  1429. X    *(str->str_ptr+str->str_cur) = '\0';
  1430. X    str->str_nok = 0;        /* invalidate number */
  1431. X    str->str_pok = 1;        /* validate pointer */
  1432. X}
  1433. X
  1434. Xstr_set(str,ptr)
  1435. Xregister STR *str;
  1436. Xregister char *ptr;
  1437. X{
  1438. X    register int len;
  1439. X
  1440. X    if (!ptr)
  1441. X    ptr = "";
  1442. X    len = strlen(ptr);
  1443. X    GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
  1444. X    bcopy(ptr,str->str_ptr,len+1);
  1445. X    str->str_cur = len;
  1446. X    str->str_nok = 0;        /* invalidate number */
  1447. X    str->str_pok = 1;        /* validate pointer */
  1448. X}
  1449. X
  1450. Xstr_chop(str,ptr)    /* like set but assuming ptr is in str */
  1451. Xregister STR *str;
  1452. Xregister char *ptr;
  1453. X{
  1454. X    if (!(str->str_pok))
  1455. X    str_2ptr(str);
  1456. X    str->str_cur -= (ptr - str->str_ptr);
  1457. X    bcopy(ptr,str->str_ptr, str->str_cur + 1);
  1458. X    str->str_nok = 0;        /* invalidate number */
  1459. X    str->str_pok = 1;        /* validate pointer */
  1460. X}
  1461. X
  1462. Xstr_ncat(str,ptr,len)
  1463. Xregister STR *str;
  1464. Xregister char *ptr;
  1465. Xregister int len;
  1466. X{
  1467. X    if (!(str->str_pok))
  1468. X    str_2ptr(str);
  1469. X    GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
  1470. X    bcopy(ptr,str->str_ptr+str->str_cur,len);
  1471. X    str->str_cur += len;
  1472. X    *(str->str_ptr+str->str_cur) = '\0';
  1473. X    str->str_nok = 0;        /* invalidate number */
  1474. X    str->str_pok = 1;        /* validate pointer */
  1475. X}
  1476. X
  1477. Xstr_scat(dstr,sstr)
  1478. XSTR *dstr;
  1479. Xregister STR *sstr;
  1480. X{
  1481. X    if (!(sstr->str_pok))
  1482. X    str_2ptr(sstr);
  1483. X    if (sstr)
  1484. X    str_ncat(dstr,sstr->str_ptr,sstr->str_cur);
  1485. X}
  1486. X
  1487. Xstr_cat(str,ptr)
  1488. Xregister STR *str;
  1489. Xregister char *ptr;
  1490. X{
  1491. X    register int len;
  1492. X
  1493. X    if (!ptr)
  1494. X    return;
  1495. X    if (!(str->str_pok))
  1496. X    str_2ptr(str);
  1497. X    len = strlen(ptr);
  1498. X    GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
  1499. X    bcopy(ptr,str->str_ptr+str->str_cur,len+1);
  1500. X    str->str_cur += len;
  1501. X    str->str_nok = 0;        /* invalidate number */
  1502. X    str->str_pok = 1;        /* validate pointer */
  1503. X}
  1504. X
  1505. Xchar *
  1506. Xstr_append_till(str,from,delim,keeplist)
  1507. Xregister STR *str;
  1508. Xregister char *from;
  1509. Xregister int delim;
  1510. Xchar *keeplist;
  1511. X{
  1512. X    register char *to;
  1513. X    register int len;
  1514. X
  1515. X    if (!from)
  1516. X    return Nullch;
  1517. X    len = strlen(from);
  1518. X    GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
  1519. X    str->str_nok = 0;        /* invalidate number */
  1520. X    str->str_pok = 1;        /* validate pointer */
  1521. X    to = str->str_ptr+str->str_cur;
  1522. X    for (; *from; from++,to++) {
  1523. X    if (*from == '\\' && from[1] && delim != '\\') {
  1524. X        if (!keeplist) {
  1525. X        if (from[1] == delim || from[1] == '\\')
  1526. X            from++;
  1527. X        else
  1528. X            *to++ = *from++;
  1529. X        }
  1530. X        else if (index(keeplist,from[1]))
  1531. X        *to++ = *from++;
  1532. X        else
  1533. X        from++;
  1534. X    }
  1535. X    else if (*from == delim)
  1536. X        break;
  1537. X    *to = *from;
  1538. X    }
  1539. X    *to = '\0';
  1540. X    str->str_cur = to - str->str_ptr;
  1541. X    return from;
  1542. X}
  1543. X
  1544. XSTR *
  1545. Xstr_new(len)
  1546. Xint len;
  1547. X{
  1548. X    register STR *str;
  1549. X    
  1550. X    if (freestrroot) {
  1551. X    str = freestrroot;
  1552. X    freestrroot = str->str_link.str_next;
  1553. X    }
  1554. X    else {
  1555. X    str = (STR *) safemalloc(sizeof(STR));
  1556. X    bzero((char*)str,sizeof(STR));
  1557. X    }
  1558. X    if (len)
  1559. X    GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
  1560. X    return str;
  1561. X}
  1562. X
  1563. Xvoid
  1564. Xstr_grow(str,len)
  1565. Xregister STR *str;
  1566. Xint len;
  1567. X{
  1568. X    if (len && str)
  1569. X    GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
  1570. X}
  1571. X
  1572. X/* make str point to what nstr did */
  1573. X
  1574. Xvoid
  1575. Xstr_replace(str,nstr)
  1576. Xregister STR *str;
  1577. Xregister STR *nstr;
  1578. X{
  1579. X    safefree(str->str_ptr);
  1580. X    str->str_ptr = nstr->str_ptr;
  1581. X    str->str_len = nstr->str_len;
  1582. X    str->str_cur = nstr->str_cur;
  1583. X    str->str_pok = nstr->str_pok;
  1584. X    if (str->str_nok = nstr->str_nok)
  1585. X    str->str_nval = nstr->str_nval;
  1586. X    safefree((char*)nstr);
  1587. X}
  1588. X
  1589. Xvoid
  1590. Xstr_free(str)
  1591. Xregister STR *str;
  1592. X{
  1593. X    if (!str)
  1594. X    return;
  1595. X    if (str->str_len)
  1596. X    str->str_ptr[0] = '\0';
  1597. X    str->str_cur = 0;
  1598. X    str->str_nok = 0;
  1599. X    str->str_pok = 0;
  1600. X    str->str_link.str_next = freestrroot;
  1601. X    freestrroot = str;
  1602. X}
  1603. X
  1604. Xstr_len(str)
  1605. Xregister STR *str;
  1606. X{
  1607. X    if (!str)
  1608. X    return 0;
  1609. X    if (!(str->str_pok))
  1610. X    str_2ptr(str);
  1611. X    if (str->str_len)
  1612. X    return str->str_cur;
  1613. X    else
  1614. X    return 0;
  1615. X}
  1616. X
  1617. Xchar *
  1618. Xstr_gets(str,fp)
  1619. Xregister STR *str;
  1620. Xregister FILE *fp;
  1621. X{
  1622. X#ifdef STDSTDIO        /* Here is some breathtakingly efficient cheating */
  1623. X
  1624. X    register char *bp;        /* we're going to steal some values */
  1625. X    register int cnt;        /*  from the stdio struct and put EVERYTHING */
  1626. X    register char *ptr;        /*   in the innermost loop into registers */
  1627. X    register char newline = '\n';    /* (assuming at least 6 registers) */
  1628. X    int i;
  1629. X    int bpx;
  1630. X
  1631. X    cnt = fp->_cnt;            /* get count into register */
  1632. X    str->str_nok = 0;            /* invalidate number */
  1633. X    str->str_pok = 1;            /* validate pointer */
  1634. X    if (str->str_len <= cnt)        /* make sure we have the room */
  1635. X    GROWSTR(&(str->str_ptr), &(str->str_len), cnt+1);
  1636. X    bp = str->str_ptr;            /* move these two too to registers */
  1637. X    ptr = fp->_ptr;
  1638. X    for (;;) {
  1639. X    while (--cnt >= 0) {            /* this */    /* eat */
  1640. X        if ((*bp++ = *ptr++) == newline)    /* really */    /* dust */
  1641. X        goto thats_all_folks;        /* screams */    /* sed :-) */ 
  1642. X    }
  1643. X    
  1644. X    fp->_cnt = cnt;            /* deregisterize cnt and ptr */
  1645. X    fp->_ptr = ptr;
  1646. X    i = _filbuf(fp);        /* get more characters */
  1647. X    cnt = fp->_cnt;
  1648. X    ptr = fp->_ptr;            /* reregisterize cnt and ptr */
  1649. X
  1650. X    bpx = bp - str->str_ptr;    /* prepare for possible relocation */
  1651. X    GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + cnt + 1);
  1652. X    bp = str->str_ptr + bpx;    /* reconstitute our pointer */
  1653. X
  1654. X    if (i == newline) {        /* all done for now? */
  1655. X        *bp++ = i;
  1656. X        goto thats_all_folks;
  1657. X    }
  1658. X    else if (i == EOF)        /* all done for ever? */
  1659. X        goto thats_all_folks;
  1660. X    *bp++ = i;            /* now go back to screaming loop */
  1661. X    }
  1662. X
  1663. Xthats_all_folks:
  1664. X    fp->_cnt = cnt;            /* put these back or we're in trouble */
  1665. X    fp->_ptr = ptr;
  1666. X    *bp = '\0';
  1667. X    str->str_cur = bp - str->str_ptr;    /* set length */
  1668. X
  1669. X#else /* !STDSTDIO */    /* The big, slow, and stupid way */
  1670. X
  1671. X    static char buf[4192];
  1672. X
  1673. X    if (fgets(buf, sizeof buf, fp) != Nullch)
  1674. X    str_set(str, buf);
  1675. X    else
  1676. X    str_set(str, No);
  1677. X
  1678. X#endif /* STDSTDIO */
  1679. X
  1680. X    return str->str_cur ? str->str_ptr : Nullch;
  1681. X}
  1682. X
  1683. Xvoid
  1684. Xstr_inc(str)
  1685. Xregister STR *str;
  1686. X{
  1687. X    register char *d;
  1688. X
  1689. X    if (!str)
  1690. X    return;
  1691. X    if (str->str_nok) {
  1692. X    str->str_nval += 1.0;
  1693. X    str->str_pok = 0;
  1694. X    return;
  1695. X    }
  1696. X    if (!str->str_pok) {
  1697. X    str->str_nval = 1.0;
  1698. X    str->str_nok = 1;
  1699. X    return;
  1700. X    }
  1701. X    for (d = str->str_ptr; *d && *d != '.'; d++) ;
  1702. X    d--;
  1703. X    if (!isdigit(*str->str_ptr) || !isdigit(*d) ) {
  1704. X        str_numset(str,atof(str->str_ptr) + 1.0);  /* punt */
  1705. X    return;
  1706. X    }
  1707. X    while (d >= str->str_ptr) {
  1708. X    if (++*d <= '9')
  1709. X        return;
  1710. X    *(d--) = '0';
  1711. X    }
  1712. X    /* oh,oh, the number grew */
  1713. X    GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + 2);
  1714. X    str->str_cur++;
  1715. X    for (d = str->str_ptr + str->str_cur; d > str->str_ptr; d--)
  1716. X    *d = d[-1];
  1717. X    *d = '1';
  1718. X}
  1719. X
  1720. Xvoid
  1721. Xstr_dec(str)
  1722. Xregister STR *str;
  1723. X{
  1724. X    register char *d;
  1725. X
  1726. X    if (!str)
  1727. X    return;
  1728. X    if (str->str_nok) {
  1729. X    str->str_nval -= 1.0;
  1730. X    str->str_pok = 0;
  1731. X    return;
  1732. X    }
  1733. X    if (!str->str_pok) {
  1734. X    str->str_nval = -1.0;
  1735. X    str->str_nok = 1;
  1736. X    return;
  1737. X    }
  1738. X    for (d = str->str_ptr; *d && *d != '.'; d++) ;
  1739. X    d--;
  1740. X    if (!isdigit(*str->str_ptr) || !isdigit(*d) || (*d == '0' && d == str->str_ptr)) {
  1741. X        str_numset(str,atof(str->str_ptr) - 1.0);  /* punt */
  1742. X    return;
  1743. X    }
  1744. X    while (d >= str->str_ptr) {
  1745. X    if (--*d >= '0')
  1746. X        return;
  1747. X    *(d--) = '9';
  1748. X    }
  1749. X}
  1750. X
  1751. X/* make a string that will exist for the duration of the expression eval */
  1752. X
  1753. XSTR *
  1754. Xstr_static(oldstr)
  1755. XSTR *oldstr;
  1756. X{
  1757. X    register STR *str = str_new(0);
  1758. X    static long tmps_size = -1;
  1759. X
  1760. X    str_sset(str,oldstr);
  1761. X    if (++tmps_max > tmps_size) {
  1762. X    tmps_size = tmps_max;
  1763. X    if (!(tmps_size & 127)) {
  1764. X        if (tmps_size)
  1765. X        tmps_list = (STR**)saferealloc((char*)tmps_list,
  1766. X            (tmps_size + 128) * sizeof(STR*) );
  1767. X        else
  1768. X        tmps_list = (STR**)safemalloc(128 * sizeof(char*));
  1769. X    }
  1770. X    }
  1771. X    tmps_list[tmps_max] = str;
  1772. X    return str;
  1773. X}
  1774. X
  1775. XSTR *
  1776. Xstr_make(s)
  1777. Xchar *s;
  1778. X{
  1779. X    register STR *str = str_new(0);
  1780. X
  1781. X    str_set(str,s);
  1782. X    return str;
  1783. X}
  1784. X
  1785. XSTR *
  1786. Xstr_nmake(n)
  1787. Xdouble n;
  1788. X{
  1789. X    register STR *str = str_new(0);
  1790. X
  1791. X    str_numset(str,n);
  1792. X    return str;
  1793. X}
  1794. !STUFFY!FUNK!
  1795. echo Extracting malloc.c
  1796. sed >malloc.c <<'!STUFFY!FUNK!' -e 's/X//'
  1797. X/* $Header: malloc.c,v 1.0 87/12/18 13:05:35 root Exp $
  1798. X *
  1799. X * $Log:    malloc.c,v $
  1800. X * Revision 1.0  87/12/18  13:05:35  root
  1801. X * Initial revision
  1802. X * 
  1803. X */
  1804. X
  1805. X#ifndef lint
  1806. Xstatic char sccsid[] = "@(#)malloc.c    4.3 (Berkeley) 9/16/83";
  1807. X#endif
  1808. X#include <stdio.h>
  1809. X
  1810. X#define RCHECK
  1811. X/*
  1812. X * malloc.c (Caltech) 2/21/82
  1813. X * Chris Kingsley, kingsley@cit-20.
  1814. X *
  1815. X * This is a very fast storage allocator.  It allocates blocks of a small 
  1816. X * number of different sizes, and keeps free lists of each size.  Blocks that
  1817. X * don't exactly fit are passed up to the next larger size.  In this 
  1818. X * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long.
  1819. X * This is designed for use in a program that uses vast quantities of memory,
  1820. X * but bombs when it runs out. 
  1821. X */
  1822. X
  1823. X#include <sys/types.h>
  1824. X
  1825. X#define    NULL 0
  1826. X
  1827. X/*
  1828. X * The overhead on a block is at least 4 bytes.  When free, this space
  1829. X * contains a pointer to the next free block, and the bottom two bits must
  1830. X * be zero.  When in use, the first byte is set to MAGIC, and the second
  1831. X * byte is the size index.  The remaining bytes are for alignment.
  1832. X * If range checking is enabled and the size of the block fits
  1833. X * in two bytes, then the top two bytes hold the size of the requested block
  1834. X * plus the range checking words, and the header word MINUS ONE.
  1835. X */
  1836. Xunion    overhead {
  1837. X    union    overhead *ov_next;    /* when free */
  1838. X    struct {
  1839. X        u_char    ovu_magic;    /* magic number */
  1840. X        u_char    ovu_index;    /* bucket # */
  1841. X#ifdef RCHECK
  1842. X        u_short    ovu_size;    /* actual block size */
  1843. X        u_int    ovu_rmagic;    /* range magic number */
  1844. X#endif
  1845. X    } ovu;
  1846. X#define    ov_magic    ovu.ovu_magic
  1847. X#define    ov_index    ovu.ovu_index
  1848. X#define    ov_size        ovu.ovu_size
  1849. X#define    ov_rmagic    ovu.ovu_rmagic
  1850. X};
  1851. X
  1852. X#define    MAGIC        0xff        /* magic # on accounting info */
  1853. X#define RMAGIC        0x55555555    /* magic # on range info */
  1854. X#ifdef RCHECK
  1855. X#define    RSLOP        sizeof (u_int)
  1856. X#else
  1857. X#define    RSLOP        0
  1858. X#endif
  1859. X
  1860. X/*
  1861. X * nextf[i] is the pointer to the next free block of size 2^(i+3).  The
  1862. X * smallest allocatable block is 8 bytes.  The overhead information
  1863. X * precedes the data area returned to the user.
  1864. X */
  1865. X#define    NBUCKETS 30
  1866. Xstatic    union overhead *nextf[NBUCKETS];
  1867. Xextern    char *sbrk();
  1868. X
  1869. X#ifdef MSTATS
  1870. X/*
  1871. X * nmalloc[i] is the difference between the number of mallocs and frees
  1872. X * for a given block size.
  1873. X */
  1874. Xstatic    u_int nmalloc[NBUCKETS];
  1875. X#include <stdio.h>
  1876. X#endif
  1877. X
  1878. X#ifdef debug
  1879. X#define    ASSERT(p)   if (!(p)) botch("p"); else
  1880. Xstatic
  1881. Xbotch(s)
  1882. X    char *s;
  1883. X{
  1884. X
  1885. X    printf("assertion botched: %s\n", s);
  1886. X    abort();
  1887. X}
  1888. X#else
  1889. X#define    ASSERT(p)
  1890. X#endif
  1891. X
  1892. Xchar *
  1893. Xmalloc(nbytes)
  1894. X    register unsigned nbytes;
  1895. X{
  1896. X      register union overhead *p;
  1897. X      register int bucket = 0;
  1898. X      register unsigned shiftr;
  1899. X
  1900. X    /*
  1901. X     * Convert amount of memory requested into
  1902. X     * closest block size stored in hash buckets
  1903. X     * which satisfies request.  Account for
  1904. X     * space used per block for accounting.
  1905. X     */
  1906. X      nbytes += sizeof (union overhead) + RSLOP;
  1907. X      nbytes = (nbytes + 3) &~ 3; 
  1908. X      shiftr = (nbytes - 1) >> 2;
  1909. X    /* apart from this loop, this is O(1) */
  1910. X      while (shiftr >>= 1)
  1911. X          bucket++;
  1912. X    /*
  1913. X     * If nothing in hash bucket right now,
  1914. X     * request more memory from the system.
  1915. X     */
  1916. X      if (nextf[bucket] == NULL)    
  1917. X          morecore(bucket);
  1918. X      if ((p = (union overhead *)nextf[bucket]) == NULL)
  1919. X          return (NULL);
  1920. X    /* remove from linked list */
  1921. X    if (*((int*)p) > 0x10000000)
  1922. X        fprintf(stderr,"Corrupt malloc ptr 0x%x at 0x%x\n",*((int*)p),p);
  1923. X      nextf[bucket] = nextf[bucket]->ov_next;
  1924. X    p->ov_magic = MAGIC;
  1925. X    p->ov_index= bucket;
  1926. X#ifdef MSTATS
  1927. X      nmalloc[bucket]++;
  1928. X#endif
  1929. X#ifdef RCHECK
  1930. X    /*
  1931. X     * Record allocated size of block and
  1932. X     * bound space with magic numbers.
  1933. X     */
  1934. X      if (nbytes <= 0x10000)
  1935. X        p->ov_size = nbytes - 1;
  1936. X    p->ov_rmagic = RMAGIC;
  1937. X      *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
  1938. X#endif
  1939. X      return ((char *)(p + 1));
  1940. X}
  1941. X
  1942. X/*
  1943. X * Allocate more memory to the indicated bucket.
  1944. X */
  1945. Xstatic
  1946. Xmorecore(bucket)
  1947. X    register bucket;
  1948. X{
  1949. X      register union overhead *op;
  1950. X      register int rnu;       /* 2^rnu bytes will be requested */
  1951. X      register int nblks;     /* become nblks blocks of the desired size */
  1952. X    register int siz;
  1953. X
  1954. X      if (nextf[bucket])
  1955. X          return;
  1956. X    /*
  1957. X     * Insure memory is allocated
  1958. X     * on a page boundary.  Should
  1959. X     * make getpageize call?
  1960. X     */
  1961. X      op = (union overhead *)sbrk(0);
  1962. X      if ((int)op & 0x3ff)
  1963. X          sbrk(1024 - ((int)op & 0x3ff));
  1964. X    /* take 2k unless the block is bigger than that */
  1965. X      rnu = (bucket <= 8) ? 11 : bucket + 3;
  1966. X      nblks = 1 << (rnu - (bucket + 3));  /* how many blocks to get */
  1967. X      if (rnu < bucket)
  1968. X        rnu = bucket;
  1969. X    op = (union overhead *)sbrk(1 << rnu);
  1970. X    /* no more room! */
  1971. X      if ((int)op == -1)
  1972. X          return;
  1973. X    /*
  1974. X     * Round up to minimum allocation size boundary
  1975. X     * and deduct from block count to reflect.
  1976. X     */
  1977. X      if ((int)op & 7) {
  1978. X          op = (union overhead *)(((int)op + 8) &~ 7);
  1979. X          nblks--;
  1980. X      }
  1981. X    /*
  1982. X     * Add new memory allocated to that on
  1983. X     * free list for this hash bucket.
  1984. X     */
  1985. X      nextf[bucket] = op;
  1986. X      siz = 1 << (bucket + 3);
  1987. X      while (--nblks > 0) {
  1988. X        op->ov_next = (union overhead *)((caddr_t)op + siz);
  1989. X        op = (union overhead *)((caddr_t)op + siz);
  1990. X      }
  1991. X}
  1992. X
  1993. Xfree(cp)
  1994. X    char *cp;
  1995. X{   
  1996. X      register int size;
  1997. X    register union overhead *op;
  1998. X
  1999. X      if (cp == NULL)
  2000. X          return;
  2001. X    op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
  2002. X#ifdef debug
  2003. X      ASSERT(op->ov_magic == MAGIC);        /* make sure it was in use */
  2004. X#else
  2005. X    if (op->ov_magic != MAGIC)
  2006. X        return;                /* sanity */
  2007. X#endif
  2008. X#ifdef RCHECK
  2009. X      ASSERT(op->ov_rmagic == RMAGIC);
  2010. X    if (op->ov_index <= 13)
  2011. X        ASSERT(*(u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP) == RMAGIC);
  2012. X#endif
  2013. X      ASSERT(op->ov_index < NBUCKETS);
  2014. X      size = op->ov_index;
  2015. X    op->ov_next = nextf[size];
  2016. X      nextf[size] = op;
  2017. X#ifdef MSTATS
  2018. X      nmalloc[size]--;
  2019. X#endif
  2020. X}
  2021. X
  2022. X/*
  2023. X * When a program attempts "storage compaction" as mentioned in the
  2024. X * old malloc man page, it realloc's an already freed block.  Usually
  2025. X * this is the last block it freed; occasionally it might be farther
  2026. X * back.  We have to search all the free lists for the block in order
  2027. X * to determine its bucket: 1st we make one pass thru the lists
  2028. X * checking only the first block in each; if that fails we search
  2029. X * ``realloc_srchlen'' blocks in each list for a match (the variable
  2030. X * is extern so the caller can modify it).  If that fails we just copy
  2031. X * however many bytes was given to realloc() and hope it's not huge.
  2032. X */
  2033. Xint realloc_srchlen = 4;    /* 4 should be plenty, -1 =>'s whole list */
  2034. X
  2035. Xchar *
  2036. Xrealloc(cp, nbytes)
  2037. X    char *cp; 
  2038. X    unsigned nbytes;
  2039. X{   
  2040. X      register u_int onb;
  2041. X    union overhead *op;
  2042. X      char *res;
  2043. X    register int i;
  2044. X    int was_alloced = 0;
  2045. X
  2046. X      if (cp == NULL)
  2047. X          return (malloc(nbytes));
  2048. X    op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
  2049. X    if (op->ov_magic == MAGIC) {
  2050. X        was_alloced++;
  2051. X        i = op->ov_index;
  2052. X    } else {
  2053. X        /*
  2054. X         * Already free, doing "compaction".
  2055. X         *
  2056. X         * Search for the old block of memory on the
  2057. X         * free list.  First, check the most common
  2058. X         * case (last element free'd), then (this failing)
  2059. X         * the last ``realloc_srchlen'' items free'd.
  2060. X         * If all lookups fail, then assume the size of
  2061. X         * the memory block being realloc'd is the
  2062. X         * smallest possible.
  2063. X         */
  2064. X        if ((i = findbucket(op, 1)) < 0 &&
  2065. X            (i = findbucket(op, realloc_srchlen)) < 0)
  2066. X            i = 0;
  2067. X    }
  2068. X    onb = (1 << (i + 3)) - sizeof (*op) - RSLOP;
  2069. X    /* avoid the copy if same size block */
  2070. X    if (was_alloced &&
  2071. X        nbytes <= onb && nbytes > (onb >> 1) - sizeof(*op) - RSLOP)
  2072. X        return(cp);
  2073. X      if ((res = malloc(nbytes)) == NULL)
  2074. X          return (NULL);
  2075. X      if (cp != res)            /* common optimization */
  2076. X        bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
  2077. X      if (was_alloced)
  2078. X        free(cp);
  2079. X      return (res);
  2080. X}
  2081. X
  2082. X/*
  2083. X * Search ``srchlen'' elements of each free list for a block whose
  2084. X * header starts at ``freep''.  If srchlen is -1 search the whole list.
  2085. X * Return bucket number, or -1 if not found.
  2086. X */
  2087. Xstatic
  2088. Xfindbucket(freep, srchlen)
  2089. X    union overhead *freep;
  2090. X    int srchlen;
  2091. X{
  2092. X    register union overhead *p;
  2093. X    register int i, j;
  2094. X
  2095. X    for (i = 0; i < NBUCKETS; i++) {
  2096. X        j = 0;
  2097. X        for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
  2098. X            if (p == freep)
  2099. X                return (i);
  2100. X            j++;
  2101. X        }
  2102. X    }
  2103. X    return (-1);
  2104. X}
  2105. X
  2106. X#ifdef MSTATS
  2107. X/*
  2108. X * mstats - print out statistics about malloc
  2109. X * 
  2110. X * Prints two lines of numbers, one showing the length of the free list
  2111. X * for each size category, the second showing the number of mallocs -
  2112. X * frees for each size category.
  2113. X */
  2114. Xmstats(s)
  2115. X    char *s;
  2116. X{
  2117. X      register int i, j;
  2118. X      register union overhead *p;
  2119. X      int totfree = 0,
  2120. X      totused = 0;
  2121. X
  2122. X      fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s);
  2123. X      for (i = 0; i < NBUCKETS; i++) {
  2124. X          for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
  2125. X              ;
  2126. X          fprintf(stderr, " %d", j);
  2127. X          totfree += j * (1 << (i + 3));
  2128. X      }
  2129. X      fprintf(stderr, "\nused:\t");
  2130. X      for (i = 0; i < NBUCKETS; i++) {
  2131. X          fprintf(stderr, " %d", nmalloc[i]);
  2132. X          totused += nmalloc[i] * (1 << (i + 3));
  2133. X      }
  2134. X      fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n",
  2135. X        totused, totfree);
  2136. X}
  2137. X#endif
  2138. !STUFFY!FUNK!
  2139. echo Extracting t/cmd.while
  2140. sed >t/cmd.while <<'!STUFFY!FUNK!' -e 's/X//'
  2141. X#!./perl
  2142. X
  2143. X# $Header: cmd.while,v 1.0 87/12/18 13:12:15 root Exp $
  2144. X
  2145. Xprint "1..10\n";
  2146. X
  2147. Xopen (tmp,'>Cmd.while.tmp') || die "Can't create Cmd.while.tmp.";
  2148. Xprint tmp "tvi925\n";
  2149. Xprint tmp "tvi920\n";
  2150. Xprint tmp "vt100\n";
  2151. Xprint tmp "Amiga\n";
  2152. Xprint tmp "paper\n";
  2153. Xclose tmp;
  2154. X
  2155. X# test "last" command
  2156. X
  2157. Xopen(fh,'Cmd.while.tmp') || die "Can't open Cmd.while.tmp.";
  2158. Xwhile (<fh>) {
  2159. X    last if /vt100/;
  2160. X}
  2161. Xif (!eof && /vt100/) {print "ok 1\n";} else {print "not ok 1\n";}
  2162. X
  2163. X# test "next" command
  2164. X
  2165. X$bad = '';
  2166. Xopen(fh,'Cmd.while.tmp') || die "Can't open Cmd.while.tmp.";
  2167. Xwhile (<fh>) {
  2168. X    next if /vt100/;
  2169. X    $bad = 1 if /vt100/;
  2170. X}
  2171. Xif (!eof || /vt100/ || $bad) {print "not ok 2\n";} else {print "ok 2\n";}
  2172. X
  2173. X# test "redo" command
  2174. X
  2175. X$bad = '';
  2176. Xopen(fh,'Cmd.while.tmp') || die "Can't open Cmd.while.tmp.";
  2177. Xwhile (<fh>) {
  2178. X    if (s/vt100/VT100/g) {
  2179. X    s/VT100/Vt100/g;
  2180. X    redo;
  2181. X    }
  2182. X    $bad = 1 if /vt100/;
  2183. X    $bad = 1 if /VT100/;
  2184. X}
  2185. Xif (!eof || $bad) {print "not ok 3\n";} else {print "ok 3\n";}
  2186. X
  2187. X# now do the same with a label and a continue block
  2188. X
  2189. X# test "last" command
  2190. X
  2191. X$badcont = '';
  2192. Xopen(fh,'Cmd.while.tmp') || die "Can't open Cmd.while.tmp.";
  2193. Xline: while (<fh>) {
  2194. X    if (/vt100/) {last line;}
  2195. X} continue {
  2196. X    $badcont = 1 if /vt100/;
  2197. X}
  2198. Xif (!eof && /vt100/) {print "ok 4\n";} else {print "not ok 4\n";}
  2199. Xif (!$badcont) {print "ok 5\n";} else {print "not ok 5\n";}
  2200. X
  2201. X# test "next" command
  2202. X
  2203. X$bad = '';
  2204. X$badcont = 1;
  2205. Xopen(fh,'Cmd.while.tmp') || die "Can't open Cmd.while.tmp.";
  2206. Xentry: while (<fh>) {
  2207. X    next entry if /vt100/;
  2208. X    $bad = 1 if /vt100/;
  2209. X} continue {
  2210. X    $badcont = '' if /vt100/;
  2211. X}
  2212. Xif (!eof || /vt100/ || $bad) {print "not ok 6\n";} else {print "ok 6\n";}
  2213. Xif (!$badcont) {print "ok 7\n";} else {print "not ok 7\n";}
  2214. X
  2215. X# test "redo" command
  2216. X
  2217. X$bad = '';
  2218. X$badcont = '';
  2219. Xopen(fh,'Cmd.while.tmp') || die "Can't open Cmd.while.tmp.";
  2220. Xloop: while (<fh>) {
  2221. X    if (s/vt100/VT100/g) {
  2222. X    s/VT100/Vt100/g;
  2223. X    redo loop;
  2224. X    }
  2225. X    $bad = 1 if /vt100/;
  2226. X    $bad = 1 if /VT100/;
  2227. X} continue {
  2228. X    $badcont = 1 if /vt100/;
  2229. X}
  2230. Xif (!eof || $bad) {print "not ok 8\n";} else {print "ok 8\n";}
  2231. Xif (!$badcont) {print "ok 9\n";} else {print "not ok 9\n";}
  2232. X
  2233. X`/bin/rm -f Cmd.while.tmp`;
  2234. X
  2235. X#$x = 0;
  2236. X#while (1) {
  2237. X#    if ($x > 1) {last;}
  2238. X#    next;
  2239. X#} continue {
  2240. X#    if ($x++ > 10) {last;}
  2241. X#    next;
  2242. X#}
  2243. X#
  2244. X#if ($x < 10) {print "ok 10\n";} else {print "not ok 10\n";}
  2245. X
  2246. X$i = 9;
  2247. X{
  2248. X    $i++;
  2249. X}
  2250. Xprint "ok $i\n";
  2251. !STUFFY!FUNK!
  2252. echo Extracting t/op.push
  2253. sed >t/op.push <<'!STUFFY!FUNK!' -e 's/X//'
  2254. X#!./perl
  2255. X
  2256. X# $Header: op.push,v 1.0 87/12/18 13:14:10 root Exp $
  2257. X
  2258. Xprint "1..2\n";
  2259. X
  2260. X@x = (1,2,3);
  2261. Xpush(@x,@x);
  2262. Xif (join(x,':') eq '1:2:3:1:2:3') {print "ok 1\n";} else {print "not ok 1\n";}
  2263. Xpush(x,4);
  2264. Xif (join(x,':') eq '1:2:3:1:2:3:4') {print "ok 2\n";} else {print "not ok 2\n";}
  2265. !STUFFY!FUNK!
  2266. echo ""
  2267. echo "End of kit 7 (of 10)"
  2268. cat /dev/null >kit7isdone
  2269. config=true
  2270. for iskit in 1 2 3 4 5 6 7 8 9 10; do
  2271.     if test -f kit${iskit}isdone; then
  2272.     echo "You have run kit ${iskit}."
  2273.     else
  2274.     echo "You still need to run kit ${iskit}."
  2275.     config=false
  2276.     fi
  2277. done
  2278. case $config in
  2279.     true)
  2280.     echo "You have run all your kits.  Please read README and then type Configure."
  2281.     chmod 755 Configure
  2282.     ;;
  2283. esac
  2284. : Someone might mail this, so...
  2285. exit
  2286.