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

  1. From: lwall@netlabs.com (Larry Wall)
  2. Newsgroups: comp.sources.misc
  3. Subject: v18i030:  perl - The perl programming language, Part12/36
  4. Message-ID: <1991Apr16.000037.22841@sparky.IMD.Sterling.COM>
  5. Date: 16 Apr 91 00:00:37 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: c1420864 1532c12a 35434d4b 81715c95
  8.  
  9. Submitted-by: Larry Wall <lwall@netlabs.com>
  10. Posting-number: Volume 18, Issue 30
  11. Archive-name: perl/part12
  12.  
  13. [There are 36 kits for perl version 4.0.]
  14.  
  15. #! /bin/sh
  16.  
  17. # Make a new directory for the perl sources, cd to it, and run kits 1
  18. # thru 36 through sh.  When all 36 kits have been run, read README.
  19.  
  20. echo "This is perl 4.0 kit 12 (of 36).  If kit 12 is complete, the line"
  21. echo '"'"End of kit 12 (of 36)"'" will echo at the end.'
  22. echo ""
  23. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  24. mkdir t t/op 2>/dev/null
  25. echo Extracting doarg.c
  26. sed >doarg.c <<'!STUFFY!FUNK!' -e 's/X//'
  27. X/* $RCSfile: doarg.c,v $$Revision: 4.0.1.1 $$Date: 91/04/11 17:40:14 $
  28. X *
  29. X *    Copyright (c) 1989, Larry Wall
  30. X *
  31. X *    You may distribute under the terms of the GNU General Public License
  32. X *    as specified in the README file that comes with the perl 3.0 kit.
  33. X *
  34. X * $Log:    doarg.c,v $
  35. X * Revision 4.0.1.1  91/04/11  17:40:14  lwall
  36. X * patch1: fixed undefined environ problem
  37. X * patch1: fixed debugger coredump on subroutines
  38. X * 
  39. X * Revision 4.0  91/03/20  01:06:42  lwall
  40. X * 4.0 baseline.
  41. X * 
  42. X */
  43. X
  44. X#include "EXTERN.h"
  45. X#include "perl.h"
  46. X
  47. X#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
  48. X#include <signal.h>
  49. X#endif
  50. X
  51. Xextern unsigned char fold[];
  52. X
  53. X#ifdef BUGGY_MSC
  54. X #pragma function(memcmp)
  55. X#endif /* BUGGY_MSC */
  56. X
  57. Xint
  58. Xdo_subst(str,arg,sp)
  59. XSTR *str;
  60. XARG *arg;
  61. Xint sp;
  62. X{
  63. X    register SPAT *spat;
  64. X    SPAT *rspat;
  65. X    register STR *dstr;
  66. X    register char *s = str_get(str);
  67. X    char *strend = s + str->str_cur;
  68. X    register char *m;
  69. X    char *c;
  70. X    register char *d;
  71. X    int clen;
  72. X    int iters = 0;
  73. X    int maxiters = (strend - s) + 10;
  74. X    register int i;
  75. X    bool once;
  76. X    char *orig;
  77. X    int safebase;
  78. X
  79. X    rspat = spat = arg[2].arg_ptr.arg_spat;
  80. X    if (!spat || !s)
  81. X    fatal("panic: do_subst");
  82. X    else if (spat->spat_runtime) {
  83. X    nointrp = "|)";
  84. X    (void)eval(spat->spat_runtime,G_SCALAR,sp);
  85. X    m = str_get(dstr = stack->ary_array[sp+1]);
  86. X    nointrp = "";
  87. X    if (spat->spat_regexp) {
  88. X        regfree(spat->spat_regexp);
  89. X        spat->spat_regexp = Null(REGEXP*);    /* required if regcomp pukes */
  90. X    }
  91. X    spat->spat_regexp = regcomp(m,m+dstr->str_cur,
  92. X        spat->spat_flags & SPAT_FOLD);
  93. X    if (spat->spat_flags & SPAT_KEEP) {
  94. X        arg_free(spat->spat_runtime);    /* it won't change, so */
  95. X        spat->spat_runtime = Nullarg;    /* no point compiling again */
  96. X    }
  97. X    }
  98. X#ifdef DEBUGGING
  99. X    if (debug & 8) {
  100. X    deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
  101. X    }
  102. X#endif
  103. X    safebase = ((!spat->spat_regexp || !spat->spat_regexp->nparens) &&
  104. X      !sawampersand);
  105. X    if (!*spat->spat_regexp->precomp && lastspat)
  106. X    spat = lastspat;
  107. X    orig = m = s;
  108. X    if (hint) {
  109. X    if (hint < s || hint > strend)
  110. X        fatal("panic: hint in do_match");
  111. X    s = hint;
  112. X    hint = Nullch;
  113. X    if (spat->spat_regexp->regback >= 0) {
  114. X        s -= spat->spat_regexp->regback;
  115. X        if (s < m)
  116. X        s = m;
  117. X    }
  118. X    else
  119. X        s = m;
  120. X    }
  121. X    else if (spat->spat_short) {
  122. X    if (spat->spat_flags & SPAT_SCANFIRST) {
  123. X        if (str->str_pok & SP_STUDIED) {
  124. X        if (screamfirst[spat->spat_short->str_rare] < 0)
  125. X            goto nope;
  126. X        else if (!(s = screaminstr(str,spat->spat_short)))
  127. X            goto nope;
  128. X        }
  129. X#ifndef lint
  130. X        else if (!(s = fbminstr((unsigned char*)s, (unsigned char*)strend,
  131. X          spat->spat_short)))
  132. X        goto nope;
  133. X#endif
  134. X        if (s && spat->spat_regexp->regback >= 0) {
  135. X        ++spat->spat_short->str_u.str_useful;
  136. X        s -= spat->spat_regexp->regback;
  137. X        if (s < m)
  138. X            s = m;
  139. X        }
  140. X        else
  141. X        s = m;
  142. X    }
  143. X    else if (!multiline && (*spat->spat_short->str_ptr != *s ||
  144. X      bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
  145. X        goto nope;
  146. X    if (--spat->spat_short->str_u.str_useful < 0) {
  147. X        str_free(spat->spat_short);
  148. X        spat->spat_short = Nullstr;    /* opt is being useless */
  149. X    }
  150. X    }
  151. X    once = ((rspat->spat_flags & SPAT_ONCE) != 0);
  152. X    if (rspat->spat_flags & SPAT_CONST) {    /* known replacement string? */
  153. X    if ((rspat->spat_repl[1].arg_type & A_MASK) == A_SINGLE)
  154. X        dstr = rspat->spat_repl[1].arg_ptr.arg_str;
  155. X    else {                    /* constant over loop, anyway */
  156. X        (void)eval(rspat->spat_repl,G_SCALAR,sp);
  157. X        dstr = stack->ary_array[sp+1];
  158. X    }
  159. X    c = str_get(dstr);
  160. X    clen = dstr->str_cur;
  161. X    if (clen <= spat->spat_slen + (int)spat->spat_regexp->regback) {
  162. X                    /* can do inplace substitution */
  163. X        if (regexec(spat->spat_regexp, s, strend, orig, 0,
  164. X          str->str_pok & SP_STUDIED ? str : Nullstr, safebase)) {
  165. X        if (spat->spat_regexp->subbase) /* oops, no we can't */
  166. X            goto long_way;
  167. X        d = s;
  168. X        lastspat = spat;
  169. X        str->str_pok = SP_VALID;    /* disable possible screamer */
  170. X        if (once) {
  171. X            m = spat->spat_regexp->startp[0];
  172. X            d = spat->spat_regexp->endp[0];
  173. X            s = orig;
  174. X            if (m - s > strend - d) {    /* faster to shorten from end */
  175. X            if (clen) {
  176. X                (void)bcopy(c, m, clen);
  177. X                m += clen;
  178. X            }
  179. X            i = strend - d;
  180. X            if (i > 0) {
  181. X                (void)bcopy(d, m, i);
  182. X                m += i;
  183. X            }
  184. X            *m = '\0';
  185. X            str->str_cur = m - s;
  186. X            STABSET(str);
  187. X            str_numset(arg->arg_ptr.arg_str, 1.0);
  188. X            stack->ary_array[++sp] = arg->arg_ptr.arg_str;
  189. X            return sp;
  190. X            }
  191. X            else if (i = m - s) {    /* faster from front */
  192. X            d -= clen;
  193. X            m = d;
  194. X            str_chop(str,d-i);
  195. X            s += i;
  196. X            while (i--)
  197. X                *--d = *--s;
  198. X            if (clen)
  199. X                (void)bcopy(c, m, clen);
  200. X            STABSET(str);
  201. X            str_numset(arg->arg_ptr.arg_str, 1.0);
  202. X            stack->ary_array[++sp] = arg->arg_ptr.arg_str;
  203. X            return sp;
  204. X            }
  205. X            else if (clen) {
  206. X            d -= clen;
  207. X            str_chop(str,d);
  208. X            (void)bcopy(c,d,clen);
  209. X            STABSET(str);
  210. X            str_numset(arg->arg_ptr.arg_str, 1.0);
  211. X            stack->ary_array[++sp] = arg->arg_ptr.arg_str;
  212. X            return sp;
  213. X            }
  214. X            else {
  215. X            str_chop(str,d);
  216. X            STABSET(str);
  217. X            str_numset(arg->arg_ptr.arg_str, 1.0);
  218. X            stack->ary_array[++sp] = arg->arg_ptr.arg_str;
  219. X            return sp;
  220. X            }
  221. X            /* NOTREACHED */
  222. X        }
  223. X        do {
  224. X            if (iters++ > maxiters)
  225. X            fatal("Substitution loop");
  226. X            m = spat->spat_regexp->startp[0];
  227. X            if (i = m - s) {
  228. X            if (s != d)
  229. X                (void)bcopy(s,d,i);
  230. X            d += i;
  231. X            }
  232. X            if (clen) {
  233. X            (void)bcopy(c,d,clen);
  234. X            d += clen;
  235. X            }
  236. X            s = spat->spat_regexp->endp[0];
  237. X        } while (regexec(spat->spat_regexp, s, strend, orig, s == m,
  238. X            Nullstr, TRUE));    /* (don't match same null twice) */
  239. X        if (s != d) {
  240. X            i = strend - s;
  241. X            str->str_cur = d - str->str_ptr + i;
  242. X            (void)bcopy(s,d,i+1);        /* include the Null */
  243. X        }
  244. X        STABSET(str);
  245. X        str_numset(arg->arg_ptr.arg_str, (double)iters);
  246. X        stack->ary_array[++sp] = arg->arg_ptr.arg_str;
  247. X        return sp;
  248. X        }
  249. X        str_numset(arg->arg_ptr.arg_str, 0.0);
  250. X        stack->ary_array[++sp] = arg->arg_ptr.arg_str;
  251. X        return sp;
  252. X    }
  253. X    }
  254. X    else
  255. X    c = Nullch;
  256. X    if (regexec(spat->spat_regexp, s, strend, orig, 0,
  257. X      str->str_pok & SP_STUDIED ? str : Nullstr, safebase)) {
  258. X    long_way:
  259. X    dstr = Str_new(25,str_len(str));
  260. X    str_nset(dstr,m,s-m);
  261. X    if (spat->spat_regexp->subbase)
  262. X        curspat = spat;
  263. X    lastspat = spat;
  264. X    do {
  265. X        if (iters++ > maxiters)
  266. X        fatal("Substitution loop");
  267. X        if (spat->spat_regexp->subbase
  268. X          && spat->spat_regexp->subbase != orig) {
  269. X        m = s;
  270. X        s = orig;
  271. X        orig = spat->spat_regexp->subbase;
  272. X        s = orig + (m - s);
  273. X        strend = s + (strend - m);
  274. X        }
  275. X        m = spat->spat_regexp->startp[0];
  276. X        str_ncat(dstr,s,m-s);
  277. X        s = spat->spat_regexp->endp[0];
  278. X        if (c) {
  279. X        if (clen)
  280. X            str_ncat(dstr,c,clen);
  281. X        }
  282. X        else {
  283. X        char *mysubbase = spat->spat_regexp->subbase;
  284. X
  285. X        spat->spat_regexp->subbase = Nullch;    /* so recursion works */
  286. X        (void)eval(rspat->spat_repl,G_SCALAR,sp);
  287. X        str_scat(dstr,stack->ary_array[sp+1]);
  288. X        if (spat->spat_regexp->subbase)
  289. X            Safefree(spat->spat_regexp->subbase);
  290. X        spat->spat_regexp->subbase = mysubbase;
  291. X        }
  292. X        if (once)
  293. X        break;
  294. X    } while (regexec(spat->spat_regexp, s, strend, orig, s == m, Nullstr,
  295. X        safebase));
  296. X    str_ncat(dstr,s,strend - s);
  297. X    str_replace(str,dstr);
  298. X    STABSET(str);
  299. X    str_numset(arg->arg_ptr.arg_str, (double)iters);
  300. X    stack->ary_array[++sp] = arg->arg_ptr.arg_str;
  301. X    return sp;
  302. X    }
  303. X    str_numset(arg->arg_ptr.arg_str, 0.0);
  304. X    stack->ary_array[++sp] = arg->arg_ptr.arg_str;
  305. X    return sp;
  306. X
  307. Xnope:
  308. X    ++spat->spat_short->str_u.str_useful;
  309. X    str_numset(arg->arg_ptr.arg_str, 0.0);
  310. X    stack->ary_array[++sp] = arg->arg_ptr.arg_str;
  311. X    return sp;
  312. X}
  313. X#ifdef BUGGY_MSC
  314. X #pragma intrinsic(memcmp)
  315. X#endif /* BUGGY_MSC */
  316. X
  317. Xint
  318. Xdo_trans(str,arg)
  319. XSTR *str;
  320. XARG *arg;
  321. X{
  322. X    register short *tbl;
  323. X    register char *s;
  324. X    register int matches = 0;
  325. X    register int ch;
  326. X    register char *send;
  327. X    register char *d;
  328. X    register int squash = arg[2].arg_len & 1;
  329. X
  330. X    tbl = (short*) arg[2].arg_ptr.arg_cval;
  331. X    s = str_get(str);
  332. X    send = s + str->str_cur;
  333. X    if (!tbl || !s)
  334. X    fatal("panic: do_trans");
  335. X#ifdef DEBUGGING
  336. X    if (debug & 8) {
  337. X    deb("2.TBL\n");
  338. X    }
  339. X#endif
  340. X    if (!arg[2].arg_len) {
  341. X    while (s < send) {
  342. X        if ((ch = tbl[*s & 0377]) >= 0) {
  343. X        matches++;
  344. X        *s = ch;
  345. X        }
  346. X        s++;
  347. X    }
  348. X    }
  349. X    else {
  350. X    d = s;
  351. X    while (s < send) {
  352. X        if ((ch = tbl[*s & 0377]) >= 0) {
  353. X        *d = ch;
  354. X        if (matches++ && squash) {
  355. X            if (d[-1] == *d)
  356. X            matches--;
  357. X            else
  358. X            d++;
  359. X        }
  360. X        else
  361. X            d++;
  362. X        }
  363. X        else if (ch == -1)        /* -1 is unmapped character */
  364. X        *d++ = *s;        /* -2 is delete character */
  365. X        s++;
  366. X    }
  367. X    matches += send - d;    /* account for disappeared chars */
  368. X    *d = '\0';
  369. X    str->str_cur = d - str->str_ptr;
  370. X    }
  371. X    STABSET(str);
  372. X    return matches;
  373. X}
  374. X
  375. Xvoid
  376. Xdo_join(str,arglast)
  377. Xregister STR *str;
  378. Xint *arglast;
  379. X{
  380. X    register STR **st = stack->ary_array;
  381. X    register int sp = arglast[1];
  382. X    register int items = arglast[2] - sp;
  383. X    register char *delim = str_get(st[sp]);
  384. X    int delimlen = st[sp]->str_cur;
  385. X
  386. X    st += ++sp;
  387. X    if (items-- > 0)
  388. X    str_sset(str, *st++);
  389. X    else
  390. X    str_set(str,"");
  391. X    if (delimlen) {
  392. X    for (; items > 0; items--,st++) {
  393. X        str_ncat(str,delim,delimlen);
  394. X        str_scat(str,*st);
  395. X    }
  396. X    }
  397. X    else {
  398. X    for (; items > 0; items--,st++)
  399. X        str_scat(str,*st);
  400. X    }
  401. X    STABSET(str);
  402. X}
  403. X
  404. Xvoid
  405. Xdo_pack(str,arglast)
  406. Xregister STR *str;
  407. Xint *arglast;
  408. X{
  409. X    register STR **st = stack->ary_array;
  410. X    register int sp = arglast[1];
  411. X    register int items;
  412. X    register char *pat = str_get(st[sp]);
  413. X    register char *patend = pat + st[sp]->str_cur;
  414. X    register int len;
  415. X    int datumtype;
  416. X    STR *fromstr;
  417. X    static char *null10 = "\0\0\0\0\0\0\0\0\0\0";
  418. X    static char *space10 = "          ";
  419. X
  420. X    /* These must not be in registers: */
  421. X    char achar;
  422. X    short ashort;
  423. X    int aint;
  424. X    unsigned int auint;
  425. X    long along;
  426. X    unsigned long aulong;
  427. X    char *aptr;
  428. X    float afloat;
  429. X    double adouble;
  430. X
  431. X    items = arglast[2] - sp;
  432. X    st += ++sp;
  433. X    str_nset(str,"",0);
  434. X    while (pat < patend) {
  435. X#define NEXTFROM (items-- > 0 ? *st++ : &str_no)
  436. X    datumtype = *pat++;
  437. X    if (*pat == '*') {
  438. X        len = index("@Xxu",datumtype) ? 0 : items;
  439. X        pat++;
  440. X    }
  441. X    else if (isdigit(*pat)) {
  442. X        len = *pat++ - '0';
  443. X        while (isdigit(*pat))
  444. X        len = (len * 10) + (*pat++ - '0');
  445. X    }
  446. X    else
  447. X        len = 1;
  448. X    switch(datumtype) {
  449. X    default:
  450. X        break;
  451. X    case '%':
  452. X        fatal("% may only be used in unpack");
  453. X    case '@':
  454. X        len -= str->str_cur;
  455. X        if (len > 0)
  456. X        goto grow;
  457. X        len = -len;
  458. X        if (len > 0)
  459. X        goto shrink;
  460. X        break;
  461. X    case 'X':
  462. X      shrink:
  463. X        if (str->str_cur < len)
  464. X        fatal("X outside of string");
  465. X        str->str_cur -= len;
  466. X        str->str_ptr[str->str_cur] = '\0';
  467. X        break;
  468. X    case 'x':
  469. X      grow:
  470. X        while (len >= 10) {
  471. X        str_ncat(str,null10,10);
  472. X        len -= 10;
  473. X        }
  474. X        str_ncat(str,null10,len);
  475. X        break;
  476. X    case 'A':
  477. X    case 'a':
  478. X        fromstr = NEXTFROM;
  479. X        aptr = str_get(fromstr);
  480. X        if (pat[-1] == '*')
  481. X        len = fromstr->str_cur;
  482. X        if (fromstr->str_cur > len)
  483. X        str_ncat(str,aptr,len);
  484. X        else {
  485. X        str_ncat(str,aptr,fromstr->str_cur);
  486. X        len -= fromstr->str_cur;
  487. X        if (datumtype == 'A') {
  488. X            while (len >= 10) {
  489. X            str_ncat(str,space10,10);
  490. X            len -= 10;
  491. X            }
  492. X            str_ncat(str,space10,len);
  493. X        }
  494. X        else {
  495. X            while (len >= 10) {
  496. X            str_ncat(str,null10,10);
  497. X            len -= 10;
  498. X            }
  499. X            str_ncat(str,null10,len);
  500. X        }
  501. X        }
  502. X        break;
  503. X    case 'B':
  504. X    case 'b':
  505. X        {
  506. X        char *savepat = pat;
  507. X        int saveitems = items;
  508. X
  509. X        fromstr = NEXTFROM;
  510. X        aptr = str_get(fromstr);
  511. X        if (pat[-1] == '*')
  512. X            len = fromstr->str_cur;
  513. X        pat = aptr;
  514. X        aint = str->str_cur;
  515. X        str->str_cur += (len+7)/8;
  516. X        STR_GROW(str, str->str_cur + 1);
  517. X        aptr = str->str_ptr + aint;
  518. X        if (len > fromstr->str_cur)
  519. X            len = fromstr->str_cur;
  520. X        aint = len;
  521. X        items = 0;
  522. X        if (datumtype == 'B') {
  523. X            for (len = 0; len++ < aint;) {
  524. X            items |= *pat++ & 1;
  525. X            if (len & 7)
  526. X                items <<= 1;
  527. X            else {
  528. X                *aptr++ = items & 0xff;
  529. X                items = 0;
  530. X            }
  531. X            }
  532. X        }
  533. X        else {
  534. X            for (len = 0; len++ < aint;) {
  535. X            if (*pat++ & 1)
  536. X                items |= 128;
  537. X            if (len & 7)
  538. X                items >>= 1;
  539. X            else {
  540. X                *aptr++ = items & 0xff;
  541. X                items = 0;
  542. X            }
  543. X            }
  544. X        }
  545. X        if (aint & 7) {
  546. X            if (datumtype == 'B')
  547. X            items <<= 7 - (aint & 7);
  548. X            else
  549. X            items >>= 7 - (aint & 7);
  550. X            *aptr++ = items & 0xff;
  551. X        }
  552. X        pat = str->str_ptr + str->str_cur;
  553. X        while (aptr <= pat)
  554. X            *aptr++ = '\0';
  555. X
  556. X        pat = savepat;
  557. X        items = saveitems;
  558. X        }
  559. X        break;
  560. X    case 'H':
  561. X    case 'h':
  562. X        {
  563. X        char *savepat = pat;
  564. X        int saveitems = items;
  565. X
  566. X        fromstr = NEXTFROM;
  567. X        aptr = str_get(fromstr);
  568. X        if (pat[-1] == '*')
  569. X            len = fromstr->str_cur;
  570. X        pat = aptr;
  571. X        aint = str->str_cur;
  572. X        str->str_cur += (len+1)/2;
  573. X        STR_GROW(str, str->str_cur + 1);
  574. X        aptr = str->str_ptr + aint;
  575. X        if (len > fromstr->str_cur)
  576. X            len = fromstr->str_cur;
  577. X        aint = len;
  578. X        items = 0;
  579. X        if (datumtype == 'H') {
  580. X            for (len = 0; len++ < aint;) {
  581. X            if (isalpha(*pat))
  582. X                items |= ((*pat++ & 15) + 9) & 15;
  583. X            else
  584. X                items |= *pat++ & 15;
  585. X            if (len & 1)
  586. X                items <<= 4;
  587. X            else {
  588. X                *aptr++ = items & 0xff;
  589. X                items = 0;
  590. X            }
  591. X            }
  592. X        }
  593. X        else {
  594. X            for (len = 0; len++ < aint;) {
  595. X            if (isalpha(*pat))
  596. X                items |= (((*pat++ & 15) + 9) & 15) << 4;
  597. X            else
  598. X                items |= (*pat++ & 15) << 4;
  599. X            if (len & 1)
  600. X                items >>= 4;
  601. X            else {
  602. X                *aptr++ = items & 0xff;
  603. X                items = 0;
  604. X            }
  605. X            }
  606. X        }
  607. X        if (aint & 1)
  608. X            *aptr++ = items & 0xff;
  609. X        pat = str->str_ptr + str->str_cur;
  610. X        while (aptr <= pat)
  611. X            *aptr++ = '\0';
  612. X
  613. X        pat = savepat;
  614. X        items = saveitems;
  615. X        }
  616. X        break;
  617. X    case 'C':
  618. X    case 'c':
  619. X        while (len-- > 0) {
  620. X        fromstr = NEXTFROM;
  621. X        aint = (int)str_gnum(fromstr);
  622. X        achar = aint;
  623. X        str_ncat(str,&achar,sizeof(char));
  624. X        }
  625. X        break;
  626. X    /* Float and double added by gnb@melba.bby.oz.au  22/11/89 */
  627. X    case 'f':
  628. X    case 'F':
  629. X        while (len-- > 0) {
  630. X        fromstr = NEXTFROM;
  631. X        afloat = (float)str_gnum(fromstr);
  632. X        str_ncat(str, (char *)&afloat, sizeof (float));
  633. X        }
  634. X        break;
  635. X    case 'd':
  636. X    case 'D':
  637. X        while (len-- > 0) {
  638. X        fromstr = NEXTFROM;
  639. X        adouble = (double)str_gnum(fromstr);
  640. X        str_ncat(str, (char *)&adouble, sizeof (double));
  641. X        }
  642. X        break;
  643. X    case 'n':
  644. X        while (len-- > 0) {
  645. X        fromstr = NEXTFROM;
  646. X        ashort = (short)str_gnum(fromstr);
  647. X#ifdef HAS_HTONS
  648. X        ashort = htons(ashort);
  649. X#endif
  650. X        str_ncat(str,(char*)&ashort,sizeof(short));
  651. X        }
  652. X        break;
  653. X    case 'S':
  654. X    case 's':
  655. X        while (len-- > 0) {
  656. X        fromstr = NEXTFROM;
  657. X        ashort = (short)str_gnum(fromstr);
  658. X        str_ncat(str,(char*)&ashort,sizeof(short));
  659. X        }
  660. X        break;
  661. X    case 'I':
  662. X        while (len-- > 0) {
  663. X        fromstr = NEXTFROM;
  664. X        auint = U_I(str_gnum(fromstr));
  665. X        str_ncat(str,(char*)&auint,sizeof(unsigned int));
  666. X        }
  667. X        break;
  668. X    case 'i':
  669. X        while (len-- > 0) {
  670. X        fromstr = NEXTFROM;
  671. X        aint = (int)str_gnum(fromstr);
  672. X        str_ncat(str,(char*)&aint,sizeof(int));
  673. X        }
  674. X        break;
  675. X    case 'N':
  676. X        while (len-- > 0) {
  677. X        fromstr = NEXTFROM;
  678. X        aulong = U_L(str_gnum(fromstr));
  679. X#ifdef HAS_HTONL
  680. X        aulong = htonl(aulong);
  681. X#endif
  682. X        str_ncat(str,(char*)&aulong,sizeof(unsigned long));
  683. X        }
  684. X        break;
  685. X    case 'L':
  686. X        while (len-- > 0) {
  687. X        fromstr = NEXTFROM;
  688. X        aulong = U_L(str_gnum(fromstr));
  689. X        str_ncat(str,(char*)&aulong,sizeof(unsigned long));
  690. X        }
  691. X        break;
  692. X    case 'l':
  693. X        while (len-- > 0) {
  694. X        fromstr = NEXTFROM;
  695. X        along = (long)str_gnum(fromstr);
  696. X        str_ncat(str,(char*)&along,sizeof(long));
  697. X        }
  698. X        break;
  699. X    case 'p':
  700. X        while (len-- > 0) {
  701. X        fromstr = NEXTFROM;
  702. X        aptr = str_get(fromstr);
  703. X        str_ncat(str,(char*)&aptr,sizeof(char*));
  704. X        }
  705. X        break;
  706. X    case 'u':
  707. X        fromstr = NEXTFROM;
  708. X        aptr = str_get(fromstr);
  709. X        aint = fromstr->str_cur;
  710. X        STR_GROW(str,aint * 4 / 3);
  711. X        if (len <= 1)
  712. X        len = 45;
  713. X        else
  714. X        len = len / 3 * 3;
  715. X        while (aint > 0) {
  716. X        int todo;
  717. X
  718. X        if (aint > len)
  719. X            todo = len;
  720. X        else
  721. X            todo = aint;
  722. X        doencodes(str, aptr, todo);
  723. X        aint -= todo;
  724. X        aptr += todo;
  725. X        }
  726. X        break;
  727. X    }
  728. X    }
  729. X    STABSET(str);
  730. X}
  731. X#undef NEXTFROM
  732. X
  733. Xdoencodes(str, s, len)
  734. Xregister STR *str;
  735. Xregister char *s;
  736. Xregister int len;
  737. X{
  738. X    char hunk[5];
  739. X
  740. X    *hunk = len + ' ';
  741. X    str_ncat(str, hunk, 1);
  742. X    hunk[4] = '\0';
  743. X    while (len > 0) {
  744. X    hunk[0] = ' ' + (077 & (*s >> 2));
  745. X    hunk[1] = ' ' + (077 & ((*s << 4) & 060 | (s[1] >> 4) & 017));
  746. X    hunk[2] = ' ' + (077 & ((s[1] << 2) & 074 | (s[2] >> 6) & 03));
  747. X    hunk[3] = ' ' + (077 & (s[2] & 077));
  748. X    str_ncat(str, hunk, 4);
  749. X    s += 3;
  750. X    len -= 3;
  751. X    }
  752. X    for (s = str->str_ptr; *s; s++) {
  753. X    if (*s == ' ')
  754. X        *s = '`';
  755. X    }
  756. X    str_ncat(str, "\n", 1);
  757. X}
  758. X
  759. Xvoid
  760. Xdo_sprintf(str,len,sarg)
  761. Xregister STR *str;
  762. Xregister int len;
  763. Xregister STR **sarg;
  764. X{
  765. X    register char *s;
  766. X    register char *t;
  767. X    register char *f;
  768. X    bool dolong;
  769. X    char ch;
  770. X    static STR *sargnull = &str_no;
  771. X    register char *send;
  772. X    char *xs;
  773. X    int xlen;
  774. X    double value;
  775. X    char *origs;
  776. X
  777. X    str_set(str,"");
  778. X    len--;            /* don't count pattern string */
  779. X    origs = t = s = str_get(*sarg);
  780. X    send = s + (*sarg)->str_cur;
  781. X    sarg++;
  782. X    for ( ; ; len--) {
  783. X    if (len <= 0 || !*sarg) {
  784. X        sarg = &sargnull;
  785. X        len = 0;
  786. X    }
  787. X    for ( ; t < send && *t != '%'; t++) ;
  788. X    if (t >= send)
  789. X        break;        /* end of format string, ignore extra args */
  790. X    f = t;
  791. X    *buf = '\0';
  792. X    xs = buf;
  793. X    dolong = FALSE;
  794. X    for (t++; t < send; t++) {
  795. X        switch (*t) {
  796. X        default:
  797. X        ch = *(++t);
  798. X        *t = '\0';
  799. X        (void)sprintf(xs,f);
  800. X        len++;
  801. X        xlen = strlen(xs);
  802. X        break;
  803. X        case '0': case '1': case '2': case '3': case '4':
  804. X        case '5': case '6': case '7': case '8': case '9': 
  805. X        case '.': case '#': case '-': case '+': case ' ':
  806. X        continue;
  807. X        case 'l':
  808. X        dolong = TRUE;
  809. X        continue;
  810. X        case 'c':
  811. X        ch = *(++t);
  812. X        *t = '\0';
  813. X        xlen = (int)str_gnum(*(sarg++));
  814. X        if (strEQ(f,"%c")) { /* some printfs fail on null chars */
  815. X            *xs = xlen;
  816. X            xs[1] = '\0';
  817. X            xlen = 1;
  818. X        }
  819. X        else {
  820. X            (void)sprintf(xs,f,xlen);
  821. X            xlen = strlen(xs);
  822. X        }
  823. X        break;
  824. X        case 'D':
  825. X        dolong = TRUE;
  826. X        /* FALL THROUGH */
  827. X        case 'd':
  828. X        ch = *(++t);
  829. X        *t = '\0';
  830. X        if (dolong)
  831. X            (void)sprintf(xs,f,(long)str_gnum(*(sarg++)));
  832. X        else
  833. X            (void)sprintf(xs,f,(int)str_gnum(*(sarg++)));
  834. X        xlen = strlen(xs);
  835. X        break;
  836. X        case 'X': case 'O':
  837. X        dolong = TRUE;
  838. X        /* FALL THROUGH */
  839. X        case 'x': case 'o': case 'u':
  840. X        ch = *(++t);
  841. X        *t = '\0';
  842. X        value = str_gnum(*(sarg++));
  843. X        if (dolong)
  844. X            (void)sprintf(xs,f,U_L(value));
  845. X        else
  846. X            (void)sprintf(xs,f,U_I(value));
  847. X        xlen = strlen(xs);
  848. X        break;
  849. X        case 'E': case 'e': case 'f': case 'G': case 'g':
  850. X        ch = *(++t);
  851. X        *t = '\0';
  852. X        (void)sprintf(xs,f,str_gnum(*(sarg++)));
  853. X        xlen = strlen(xs);
  854. X        break;
  855. X        case 's':
  856. X        ch = *(++t);
  857. X        *t = '\0';
  858. X        xs = str_get(*sarg);
  859. X        xlen = (*sarg)->str_cur;
  860. X        if (*xs == 'S' && xs[1] == 't' && xs[2] == 'B' && xs[3] == '\0'
  861. X          && xlen == sizeof(STBP)) {
  862. X            STR *tmpstr = Str_new(24,0);
  863. X
  864. X            stab_fullname(tmpstr, ((STAB*)(*sarg))); /* a stab value! */
  865. X            sprintf(tokenbuf,"*%s",tmpstr->str_ptr);
  866. X                    /* reformat to non-binary */
  867. X            xs = tokenbuf;
  868. X            xlen = strlen(tokenbuf);
  869. X            str_free(tmpstr);
  870. X        }
  871. X        sarg++;
  872. X        if (strEQ(f,"%s")) {    /* some printfs fail on >128 chars */
  873. X            break;        /* so handle simple case */
  874. X        }
  875. X        strcpy(tokenbuf+64,f);    /* sprintf($s,...$s...) */
  876. X        *t = ch;
  877. X        (void)sprintf(buf,tokenbuf+64,xs);
  878. X        xs = buf;
  879. X        xlen = strlen(xs);
  880. X        break;
  881. X        }
  882. X        /* end of switch, copy results */
  883. X        *t = ch;
  884. X        STR_GROW(str, str->str_cur + (f - s) + len + 1);
  885. X        str_ncat(str, s, f - s);
  886. X        str_ncat(str, xs, xlen);
  887. X        s = t;
  888. X        break;        /* break from for loop */
  889. X    }
  890. X    }
  891. X    str_ncat(str, s, t - s);
  892. X    STABSET(str);
  893. X}
  894. X
  895. XSTR *
  896. Xdo_push(ary,arglast)
  897. Xregister ARRAY *ary;
  898. Xint *arglast;
  899. X{
  900. X    register STR **st = stack->ary_array;
  901. X    register int sp = arglast[1];
  902. X    register int items = arglast[2] - sp;
  903. X    register STR *str = &str_undef;
  904. X
  905. X    for (st += ++sp; items > 0; items--,st++) {
  906. X    str = Str_new(26,0);
  907. X    if (*st)
  908. X        str_sset(str,*st);
  909. X    (void)apush(ary,str);
  910. X    }
  911. X    return str;
  912. X}
  913. X
  914. Xvoid
  915. Xdo_unshift(ary,arglast)
  916. Xregister ARRAY *ary;
  917. Xint *arglast;
  918. X{
  919. X    register STR **st = stack->ary_array;
  920. X    register int sp = arglast[1];
  921. X    register int items = arglast[2] - sp;
  922. X    register STR *str;
  923. X    register int i;
  924. X
  925. X    aunshift(ary,items);
  926. X    i = 0;
  927. X    for (st += ++sp; i < items; i++,st++) {
  928. X    str = Str_new(27,0);
  929. X    str_sset(str,*st);
  930. X    (void)astore(ary,i,str);
  931. X    }
  932. X}
  933. X
  934. Xint
  935. Xdo_subr(arg,gimme,arglast)
  936. Xregister ARG *arg;
  937. Xint gimme;
  938. Xint *arglast;
  939. X{
  940. X    register STR **st = stack->ary_array;
  941. X    register int sp = arglast[1];
  942. X    register int items = arglast[2] - sp;
  943. X    register SUBR *sub;
  944. X    STR *str;
  945. X    STAB *stab;
  946. X    int oldsave = savestack->ary_fill;
  947. X    int oldtmps_base = tmps_base;
  948. X    int hasargs = ((arg[2].arg_type & A_MASK) != A_NULL);
  949. X    register CSV *csv;
  950. X
  951. X    if ((arg[1].arg_type & A_MASK) == A_WORD)
  952. X    stab = arg[1].arg_ptr.arg_stab;
  953. X    else {
  954. X    STR *tmpstr = stab_val(arg[1].arg_ptr.arg_stab);
  955. X
  956. X    if (tmpstr)
  957. X        stab = stabent(str_get(tmpstr),TRUE);
  958. X    else
  959. X        stab = Nullstab;
  960. X    }
  961. X    if (!stab)
  962. X    fatal("Undefined subroutine called");
  963. X    if (!(sub = stab_sub(stab))) {
  964. X    STR *tmpstr = arg[0].arg_ptr.arg_str;
  965. X
  966. X    stab_fullname(tmpstr, stab);
  967. X    fatal("Undefined subroutine \"%s\" called",tmpstr->str_ptr);
  968. X    }
  969. X    if (arg->arg_type == O_DBSUBR && !sub->usersub) {
  970. X    str = stab_val(DBsub);
  971. X    saveitem(str);
  972. X    stab_fullname(str,stab);
  973. X    sub = stab_sub(DBsub);
  974. X    if (!sub)
  975. X        fatal("No DBsub routine");
  976. X    }
  977. X    str = Str_new(15, sizeof(CSV));
  978. X    str->str_state = SS_SCSV;
  979. X    (void)apush(savestack,str);
  980. X    csv = (CSV*)str->str_ptr;
  981. X    csv->sub = sub;
  982. X    csv->stab = stab;
  983. X    csv->curcsv = curcsv;
  984. X    csv->curcmd = curcmd;
  985. X    csv->depth = sub->depth;
  986. X    csv->wantarray = gimme;
  987. X    csv->hasargs = hasargs;
  988. X    curcsv = csv;
  989. X    if (sub->usersub) {
  990. X    csv->hasargs = 0;
  991. X    csv->savearray = Null(ARRAY*);;
  992. X    csv->argarray = Null(ARRAY*);
  993. X    st[sp] = arg->arg_ptr.arg_str;
  994. X    if (!hasargs)
  995. X        items = 0;
  996. X    return (*sub->usersub)(sub->userindex,sp,items);
  997. X    }
  998. X    if (hasargs) {
  999. X    csv->savearray = stab_xarray(defstab);
  1000. X    csv->argarray = afake(defstab, items, &st[sp+1]);
  1001. X    stab_xarray(defstab) = csv->argarray;
  1002. X    }
  1003. X    sub->depth++;
  1004. X    if (sub->depth >= 2) {    /* save temporaries on recursion? */
  1005. X    if (sub->depth == 100 && dowarn)
  1006. X        warn("Deep recursion on subroutine \"%s\"",stab_name(stab));
  1007. X    savelist(sub->tosave->ary_array,sub->tosave->ary_fill);
  1008. X    }
  1009. X    tmps_base = tmps_max;
  1010. X    sp = cmd_exec(sub->cmd,gimme, --sp);    /* so do it already */
  1011. X    st = stack->ary_array;
  1012. X
  1013. X    tmps_base = oldtmps_base;
  1014. X    for (items = arglast[0] + 1; items <= sp; items++)
  1015. X    st[items] = str_mortal(st[items]);
  1016. X        /* in case restore wipes old str */
  1017. X    restorelist(oldsave);
  1018. X    return sp;
  1019. X}
  1020. X
  1021. Xint
  1022. Xdo_assign(arg,gimme,arglast)
  1023. Xregister ARG *arg;
  1024. Xint gimme;
  1025. Xint *arglast;
  1026. X{
  1027. X
  1028. X    register STR **st = stack->ary_array;
  1029. X    STR **firstrelem = st + arglast[1] + 1;
  1030. X    STR **firstlelem = st + arglast[0] + 1;
  1031. X    STR **lastrelem = st + arglast[2];
  1032. X    STR **lastlelem = st + arglast[1];
  1033. X    register STR **relem;
  1034. X    register STR **lelem;
  1035. X
  1036. X    register STR *str;
  1037. X    register ARRAY *ary;
  1038. X    register int makelocal;
  1039. X    HASH *hash;
  1040. X    int i;
  1041. X
  1042. X    makelocal = (arg->arg_flags & AF_LOCAL);
  1043. X    localizing = makelocal;
  1044. X    delaymagic = DM_DELAY;        /* catch simultaneous items */
  1045. X
  1046. X    /* If there's a common identifier on both sides we have to take
  1047. X     * special care that assigning the identifier on the left doesn't
  1048. X     * clobber a value on the right that's used later in the list.
  1049. X     */
  1050. X    if (arg->arg_flags & AF_COMMON) {
  1051. X    for (relem = firstrelem; relem <= lastrelem; relem++) {
  1052. X        if (str = *relem)
  1053. X        *relem = str_mortal(str);
  1054. X    }
  1055. X    }
  1056. X    relem = firstrelem;
  1057. X    lelem = firstlelem;
  1058. X    ary = Null(ARRAY*);
  1059. X    hash = Null(HASH*);
  1060. X    while (lelem <= lastlelem) {
  1061. X    str = *lelem++;
  1062. X    if (str->str_state >= SS_HASH) {
  1063. X        if (str->str_state == SS_ARY) {
  1064. X        if (makelocal)
  1065. X            ary = saveary(str->str_u.str_stab);
  1066. X        else {
  1067. X            ary = stab_array(str->str_u.str_stab);
  1068. X            ary->ary_fill = -1;
  1069. X        }
  1070. X        i = 0;
  1071. X        while (relem <= lastrelem) {    /* gobble up all the rest */
  1072. X            str = Str_new(28,0);
  1073. X            if (*relem)
  1074. X            str_sset(str,*relem);
  1075. X            *(relem++) = str;
  1076. X            (void)astore(ary,i++,str);
  1077. X        }
  1078. X        }
  1079. X        else if (str->str_state == SS_HASH) {
  1080. X        char *tmps;
  1081. X        STR *tmpstr;
  1082. X        int magic = 0;
  1083. X        STAB *tmpstab = str->str_u.str_stab;
  1084. X
  1085. X        if (makelocal)
  1086. X            hash = savehash(str->str_u.str_stab);
  1087. X        else {
  1088. X            hash = stab_hash(str->str_u.str_stab);
  1089. X            if (tmpstab == envstab) {
  1090. X            magic = 'E';
  1091. X            environ[0] = Nullch;
  1092. X            }
  1093. X            else if (tmpstab == sigstab) {
  1094. X            magic = 'S';
  1095. X#ifndef NSIG
  1096. X#define NSIG 32
  1097. X#endif
  1098. X            for (i = 1; i < NSIG; i++)
  1099. X                signal(i, SIG_DFL);    /* crunch, crunch, crunch */
  1100. X            }
  1101. X#ifdef SOME_DBM
  1102. X            else if (hash->tbl_dbm)
  1103. X            magic = 'D';
  1104. X#endif
  1105. X            hclear(hash, magic == 'D');    /* wipe any dbm file too */
  1106. X
  1107. X        }
  1108. X        while (relem < lastrelem) {    /* gobble up all the rest */
  1109. X            if (*relem)
  1110. X            str = *(relem++);
  1111. X            else
  1112. X            str = &str_no, relem++;
  1113. X            tmps = str_get(str);
  1114. X            tmpstr = Str_new(29,0);
  1115. X            if (*relem)
  1116. X            str_sset(tmpstr,*relem);    /* value */
  1117. X            *(relem++) = tmpstr;
  1118. X            (void)hstore(hash,tmps,str->str_cur,tmpstr,0);
  1119. X            if (magic) {
  1120. X            str_magic(tmpstr, tmpstab, magic, tmps, str->str_cur);
  1121. X            stabset(tmpstr->str_magic, tmpstr);
  1122. X            }
  1123. X        }
  1124. X        }
  1125. X        else
  1126. X        fatal("panic: do_assign");
  1127. X    }
  1128. X    else {
  1129. X        if (makelocal)
  1130. X        saveitem(str);
  1131. X        if (relem <= lastrelem) {
  1132. X        str_sset(str, *relem);
  1133. X        *(relem++) = str;
  1134. X        }
  1135. X        else {
  1136. X        str_sset(str, &str_undef);
  1137. X        if (gimme == G_ARRAY) {
  1138. X            i = ++lastrelem - firstrelem;
  1139. X            relem++;        /* tacky, I suppose */
  1140. X            astore(stack,i,str);
  1141. X            if (st != stack->ary_array) {
  1142. X            st = stack->ary_array;
  1143. X            firstrelem = st + arglast[1] + 1;
  1144. X            firstlelem = st + arglast[0] + 1;
  1145. X            lastlelem = st + arglast[1];
  1146. X            lastrelem = st + i;
  1147. X            relem = lastrelem + 1;
  1148. X            }
  1149. X        }
  1150. X        }
  1151. X        STABSET(str);
  1152. X    }
  1153. X    }
  1154. X    if (delaymagic > 1) {
  1155. X    if (delaymagic & DM_REUID) {
  1156. X#ifdef HAS_SETREUID
  1157. X        setreuid(uid,euid);
  1158. X#else
  1159. X        if (uid != euid || setuid(uid) < 0)
  1160. X        fatal("No setreuid available");
  1161. X#endif
  1162. X    }
  1163. X    if (delaymagic & DM_REGID) {
  1164. X#ifdef HAS_SETREGID
  1165. X        setregid(gid,egid);
  1166. X#else
  1167. X        if (gid != egid || setgid(gid) < 0)
  1168. X        fatal("No setregid available");
  1169. X#endif
  1170. X    }
  1171. X    }
  1172. X    delaymagic = 0;
  1173. X    localizing = FALSE;
  1174. X    if (gimme == G_ARRAY) {
  1175. X    i = lastrelem - firstrelem + 1;
  1176. X    if (ary || hash)
  1177. X        Copy(firstrelem, firstlelem, i, STR*);
  1178. X    return arglast[0] + i;
  1179. X    }
  1180. X    else {
  1181. X    str_numset(arg->arg_ptr.arg_str,(double)(arglast[2] - arglast[1]));
  1182. X    *firstlelem = arg->arg_ptr.arg_str;
  1183. X    return arglast[0] + 1;
  1184. X    }
  1185. X}
  1186. X
  1187. Xint
  1188. Xdo_study(str,arg,gimme,arglast)
  1189. XSTR *str;
  1190. XARG *arg;
  1191. Xint gimme;
  1192. Xint *arglast;
  1193. X{
  1194. X    register unsigned char *s;
  1195. X    register int pos = str->str_cur;
  1196. X    register int ch;
  1197. X    register int *sfirst;
  1198. X    register int *snext;
  1199. X    static int maxscream = -1;
  1200. X    static STR *lastscream = Nullstr;
  1201. X    int retval;
  1202. X    int retarg = arglast[0] + 1;
  1203. X
  1204. X#ifndef lint
  1205. X    s = (unsigned char*)(str_get(str));
  1206. X#else
  1207. X    s = Null(unsigned char*);
  1208. X#endif
  1209. X    if (lastscream)
  1210. X    lastscream->str_pok &= ~SP_STUDIED;
  1211. X    lastscream = str;
  1212. X    if (pos <= 0) {
  1213. X    retval = 0;
  1214. X    goto ret;
  1215. X    }
  1216. X    if (pos > maxscream) {
  1217. X    if (maxscream < 0) {
  1218. X        maxscream = pos + 80;
  1219. X        New(301,screamfirst, 256, int);
  1220. X        New(302,screamnext, maxscream, int);
  1221. X    }
  1222. X    else {
  1223. X        maxscream = pos + pos / 4;
  1224. X        Renew(screamnext, maxscream, int);
  1225. X    }
  1226. X    }
  1227. X
  1228. X    sfirst = screamfirst;
  1229. X    snext = screamnext;
  1230. X
  1231. X    if (!sfirst || !snext)
  1232. X    fatal("do_study: out of memory");
  1233. X
  1234. X    for (ch = 256; ch; --ch)
  1235. X    *sfirst++ = -1;
  1236. X    sfirst -= 256;
  1237. X
  1238. X    while (--pos >= 0) {
  1239. X    ch = s[pos];
  1240. X    if (sfirst[ch] >= 0)
  1241. X        snext[pos] = sfirst[ch] - pos;
  1242. X    else
  1243. X        snext[pos] = -pos;
  1244. X    sfirst[ch] = pos;
  1245. X
  1246. X    /* If there were any case insensitive searches, we must assume they
  1247. X     * all are.  This speeds up insensitive searches much more than
  1248. X     * it slows down sensitive ones.
  1249. X     */
  1250. X    if (sawi)
  1251. X        sfirst[fold[ch]] = pos;
  1252. X    }
  1253. X
  1254. X    str->str_pok |= SP_STUDIED;
  1255. X    retval = 1;
  1256. X  ret:
  1257. X    str_numset(arg->arg_ptr.arg_str,(double)retval);
  1258. X    stack->ary_array[retarg] = arg->arg_ptr.arg_str;
  1259. X    return retarg;
  1260. X}
  1261. X
  1262. Xint
  1263. Xdo_defined(str,arg,gimme,arglast)
  1264. XSTR *str;
  1265. Xregister ARG *arg;
  1266. Xint gimme;
  1267. Xint *arglast;
  1268. X{
  1269. X    register int type;
  1270. X    register int retarg = arglast[0] + 1;
  1271. X    int retval;
  1272. X    ARRAY *ary;
  1273. X    HASH *hash;
  1274. X
  1275. X    if ((arg[1].arg_type & A_MASK) != A_LEXPR)
  1276. X    fatal("Illegal argument to defined()");
  1277. X    arg = arg[1].arg_ptr.arg_arg;
  1278. X    type = arg->arg_type;
  1279. X
  1280. X    if (type == O_SUBR || type == O_DBSUBR)
  1281. X    retval = stab_sub(arg[1].arg_ptr.arg_stab) != 0;
  1282. X    else if (type == O_ARRAY || type == O_LARRAY ||
  1283. X         type == O_ASLICE || type == O_LASLICE )
  1284. X    retval = ((ary = stab_xarray(arg[1].arg_ptr.arg_stab)) != 0
  1285. X        && ary->ary_max >= 0 );
  1286. X    else if (type == O_HASH || type == O_LHASH ||
  1287. X         type == O_HSLICE || type == O_LHSLICE )
  1288. X    retval = ((hash = stab_xhash(arg[1].arg_ptr.arg_stab)) != 0
  1289. X        && hash->tbl_array);
  1290. X    else
  1291. X    retval = FALSE;
  1292. X    str_numset(str,(double)retval);
  1293. X    stack->ary_array[retarg] = str;
  1294. X    return retarg;
  1295. X}
  1296. X
  1297. Xint
  1298. Xdo_undef(str,arg,gimme,arglast)
  1299. XSTR *str;
  1300. Xregister ARG *arg;
  1301. Xint gimme;
  1302. Xint *arglast;
  1303. X{
  1304. X    register int type;
  1305. X    register STAB *stab;
  1306. X    int retarg = arglast[0] + 1;
  1307. X
  1308. X    if ((arg[1].arg_type & A_MASK) != A_LEXPR)
  1309. X    fatal("Illegal argument to undef()");
  1310. X    arg = arg[1].arg_ptr.arg_arg;
  1311. X    type = arg->arg_type;
  1312. X
  1313. X    if (type == O_ARRAY || type == O_LARRAY) {
  1314. X    stab = arg[1].arg_ptr.arg_stab;
  1315. X    afree(stab_xarray(stab));
  1316. X    stab_xarray(stab) = Null(ARRAY*);
  1317. X    }
  1318. X    else if (type == O_HASH || type == O_LHASH) {
  1319. X    stab = arg[1].arg_ptr.arg_stab;
  1320. X    if (stab == envstab)
  1321. X        environ[0] = Nullch;
  1322. X    else if (stab == sigstab) {
  1323. X        int i;
  1324. X
  1325. X        for (i = 1; i < NSIG; i++)
  1326. X        signal(i, SIG_DFL);    /* munch, munch, munch */
  1327. X    }
  1328. X    (void)hfree(stab_xhash(stab), TRUE);
  1329. X    stab_xhash(stab) = Null(HASH*);
  1330. X    }
  1331. X    else if (type == O_SUBR || type == O_DBSUBR) {
  1332. X    stab = arg[1].arg_ptr.arg_stab;
  1333. X    if (stab_sub(stab)) {
  1334. X        cmd_free(stab_sub(stab)->cmd);
  1335. X        stab_sub(stab)->cmd = Nullcmd;
  1336. X        afree(stab_sub(stab)->tosave);
  1337. X        Safefree(stab_sub(stab));
  1338. X        stab_sub(stab) = Null(SUBR*);
  1339. X    }
  1340. X    }
  1341. X    else
  1342. X    fatal("Can't undefine that kind of object");
  1343. X    str_numset(str,0.0);
  1344. X    stack->ary_array[retarg] = str;
  1345. X    return retarg;
  1346. X}
  1347. X
  1348. Xint
  1349. Xdo_vec(lvalue,astr,arglast)
  1350. Xint lvalue;
  1351. XSTR *astr;
  1352. Xint *arglast;
  1353. X{
  1354. X    STR **st = stack->ary_array;
  1355. X    int sp = arglast[0];
  1356. X    register STR *str = st[++sp];
  1357. X    register int offset = (int)str_gnum(st[++sp]);
  1358. X    register int size = (int)str_gnum(st[++sp]);
  1359. X    unsigned char *s = (unsigned char*)str_get(str);
  1360. X    unsigned long retnum;
  1361. X    int len;
  1362. X
  1363. X    sp = arglast[1];
  1364. X    offset *= size;        /* turn into bit offset */
  1365. X    len = (offset + size + 7) / 8;
  1366. X    if (offset < 0 || size < 1)
  1367. X    retnum = 0;
  1368. X    else if (!lvalue && len > str->str_cur)
  1369. X    retnum = 0;
  1370. X    else {
  1371. X    if (len > str->str_cur) {
  1372. X        STR_GROW(str,len);
  1373. X        (void)bzero(str->str_ptr + str->str_cur, len - str->str_cur);
  1374. X        str->str_cur = len;
  1375. X    }
  1376. X    s = (unsigned char*)str_get(str);
  1377. X    if (size < 8)
  1378. X        retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
  1379. X    else {
  1380. X        offset >>= 3;
  1381. X        if (size == 8)
  1382. X        retnum = s[offset];
  1383. X        else if (size == 16)
  1384. X        retnum = (s[offset] << 8) + s[offset+1];
  1385. X        else if (size == 32)
  1386. X        retnum = (s[offset] << 24) + (s[offset + 1] << 16) +
  1387. X            (s[offset + 2] << 8) + s[offset+3];
  1388. X    }
  1389. X
  1390. X    if (lvalue) {                      /* it's an lvalue! */
  1391. X        struct lstring *lstr = (struct lstring*)astr;
  1392. X
  1393. X        astr->str_magic = str;
  1394. X        st[sp]->str_rare = 'v';
  1395. X        lstr->lstr_offset = offset;
  1396. X        lstr->lstr_len = size;
  1397. X    }
  1398. X    }
  1399. X
  1400. X    str_numset(astr,(double)retnum);
  1401. X    st[sp] = astr;
  1402. X    return sp;
  1403. X}
  1404. X
  1405. Xvoid
  1406. Xdo_vecset(mstr,str)
  1407. XSTR *mstr;
  1408. XSTR *str;
  1409. X{
  1410. X    struct lstring *lstr = (struct lstring*)str;
  1411. X    register int offset;
  1412. X    register int size;
  1413. X    register unsigned char *s = (unsigned char*)mstr->str_ptr;
  1414. X    register unsigned long lval = U_L(str_gnum(str));
  1415. X    int mask;
  1416. X
  1417. X    mstr->str_rare = 0;
  1418. X    str->str_magic = Nullstr;
  1419. X    offset = lstr->lstr_offset;
  1420. X    size = lstr->lstr_len;
  1421. X    if (size < 8) {
  1422. X    mask = (1 << size) - 1;
  1423. X    size = offset & 7;
  1424. X    lval &= mask;
  1425. X    offset >>= 3;
  1426. X    s[offset] &= ~(mask << size);
  1427. X    s[offset] |= lval << size;
  1428. X    }
  1429. X    else {
  1430. X    if (size == 8)
  1431. X        s[offset] = lval & 255;
  1432. X    else if (size == 16) {
  1433. X        s[offset] = (lval >> 8) & 255;
  1434. X        s[offset+1] = lval & 255;
  1435. X    }
  1436. X    else if (size == 32) {
  1437. X        s[offset] = (lval >> 24) & 255;
  1438. X        s[offset+1] = (lval >> 16) & 255;
  1439. X        s[offset+2] = (lval >> 8) & 255;
  1440. X        s[offset+3] = lval & 255;
  1441. X    }
  1442. X    }
  1443. X}
  1444. X
  1445. Xdo_chop(astr,str)
  1446. Xregister STR *astr;
  1447. Xregister STR *str;
  1448. X{
  1449. X    register char *tmps;
  1450. X    register int i;
  1451. X    ARRAY *ary;
  1452. X    HASH *hash;
  1453. X    HENT *entry;
  1454. X
  1455. X    if (!str)
  1456. X    return;
  1457. X    if (str->str_state == SS_ARY) {
  1458. X    ary = stab_array(str->str_u.str_stab);
  1459. X    for (i = 0; i <= ary->ary_fill; i++)
  1460. X        do_chop(astr,ary->ary_array[i]);
  1461. X    return;
  1462. X    }
  1463. X    if (str->str_state == SS_HASH) {
  1464. X    hash = stab_hash(str->str_u.str_stab);
  1465. X    (void)hiterinit(hash);
  1466. X    while (entry = hiternext(hash))
  1467. X        do_chop(astr,hiterval(hash,entry));
  1468. X    return;
  1469. X    }
  1470. X    tmps = str_get(str);
  1471. X    if (!tmps)
  1472. X    return;
  1473. X    tmps += str->str_cur - (str->str_cur != 0);
  1474. X    str_nset(astr,tmps,1);    /* remember last char */
  1475. X    *tmps = '\0';                /* wipe it out */
  1476. X    str->str_cur = tmps - str->str_ptr;
  1477. X    str->str_nok = 0;
  1478. X    STABSET(str);
  1479. X}
  1480. X
  1481. Xdo_vop(optype,str,left,right)
  1482. XSTR *str;
  1483. XSTR *left;
  1484. XSTR *right;
  1485. X{
  1486. X    register char *s;
  1487. X    register char *l = str_get(left);
  1488. X    register char *r = str_get(right);
  1489. X    register int len;
  1490. X
  1491. X    len = left->str_cur;
  1492. X    if (len > right->str_cur)
  1493. X    len = right->str_cur;
  1494. X    if (str->str_cur > len)
  1495. X    str->str_cur = len;
  1496. X    else if (str->str_cur < len) {
  1497. X    STR_GROW(str,len);
  1498. X    (void)bzero(str->str_ptr + str->str_cur, len - str->str_cur);
  1499. X    str->str_cur = len;
  1500. X    }
  1501. X    s = str->str_ptr;
  1502. X    if (!s) {
  1503. X    str_nset(str,"",0);
  1504. X    s = str->str_ptr;
  1505. X    }
  1506. X    switch (optype) {
  1507. X    case O_BIT_AND:
  1508. X    while (len--)
  1509. X        *s++ = *l++ & *r++;
  1510. X    break;
  1511. X    case O_XOR:
  1512. X    while (len--)
  1513. X        *s++ = *l++ ^ *r++;
  1514. X    goto mop_up;
  1515. X    case O_BIT_OR:
  1516. X    while (len--)
  1517. X        *s++ = *l++ | *r++;
  1518. X      mop_up:
  1519. X    len = str->str_cur;
  1520. X    if (right->str_cur > len)
  1521. X        str_ncat(str,right->str_ptr+len,right->str_cur - len);
  1522. X    else if (left->str_cur > len)
  1523. X        str_ncat(str,left->str_ptr+len,left->str_cur - len);
  1524. X    break;
  1525. X    }
  1526. X}
  1527. X
  1528. Xint
  1529. Xdo_syscall(arglast)
  1530. Xint *arglast;
  1531. X{
  1532. X    register STR **st = stack->ary_array;
  1533. X    register int sp = arglast[1];
  1534. X    register int items = arglast[2] - sp;
  1535. X    long arg[8];
  1536. X    register int i = 0;
  1537. X    int retval = -1;
  1538. X
  1539. X#ifdef HAS_SYSCALL
  1540. X#ifdef TAINT
  1541. X    for (st += ++sp; items--; st++)
  1542. X    tainted |= (*st)->str_tainted;
  1543. X    st = stack->ary_array;
  1544. X    sp = arglast[1];
  1545. X    items = arglast[2] - sp;
  1546. X#endif
  1547. X#ifdef TAINT
  1548. X    taintproper("Insecure dependency in syscall");
  1549. X#endif
  1550. X    /* This probably won't work on machines where sizeof(long) != sizeof(int)
  1551. X     * or where sizeof(long) != sizeof(char*).  But such machines will
  1552. X     * not likely have syscall implemented either, so who cares?
  1553. X     */
  1554. X    while (items--) {
  1555. X    if (st[++sp]->str_nok || !i)
  1556. X        arg[i++] = (long)str_gnum(st[sp]);
  1557. X#ifndef lint
  1558. X    else
  1559. X        arg[i++] = (long)st[sp]->str_ptr;
  1560. X#endif /* lint */
  1561. X    }
  1562. X    sp = arglast[1];
  1563. X    items = arglast[2] - sp;
  1564. X    switch (items) {
  1565. X    case 0:
  1566. X    fatal("Too few args to syscall");
  1567. X    case 1:
  1568. X    retval = syscall(arg[0]);
  1569. X    break;
  1570. X    case 2:
  1571. X    retval = syscall(arg[0],arg[1]);
  1572. X    break;
  1573. X    case 3:
  1574. X    retval = syscall(arg[0],arg[1],arg[2]);
  1575. X    break;
  1576. X    case 4:
  1577. X    retval = syscall(arg[0],arg[1],arg[2],arg[3]);
  1578. X    break;
  1579. X    case 5:
  1580. X    retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4]);
  1581. X    break;
  1582. X    case 6:
  1583. X    retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
  1584. X    break;
  1585. X    case 7:
  1586. X    retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
  1587. X    break;
  1588. X    case 8:
  1589. X    retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
  1590. X      arg[7]);
  1591. X    break;
  1592. X    }
  1593. X    return retval;
  1594. X#else
  1595. X    fatal("syscall() unimplemented");
  1596. X#endif
  1597. X}
  1598. X
  1599. X
  1600. !STUFFY!FUNK!
  1601. echo Extracting malloc.c
  1602. sed >malloc.c <<'!STUFFY!FUNK!' -e 's/X//'
  1603. X/* $RCSfile: malloc.c,v $$Revision: 4.0.1.1 $$Date: 91/04/11 17:48:31 $
  1604. X *
  1605. X * $Log:    malloc.c,v $
  1606. X * Revision 4.0.1.1  91/04/11  17:48:31  lwall
  1607. X * patch1: Configure now figures out malloc ptr type
  1608. X * 
  1609. X * Revision 4.0  91/03/20  01:28:52  lwall
  1610. X * 4.0 baseline.
  1611. X * 
  1612. X */
  1613. X
  1614. X#ifndef lint
  1615. Xstatic char sccsid[] = "@(#)malloc.c    4.3 (Berkeley) 9/16/83";
  1616. X
  1617. X#ifdef DEBUGGING
  1618. X#define RCHECK
  1619. X#endif
  1620. X/*
  1621. X * malloc.c (Caltech) 2/21/82
  1622. X * Chris Kingsley, kingsley@cit-20.
  1623. X *
  1624. X * This is a very fast storage allocator.  It allocates blocks of a small 
  1625. X * number of different sizes, and keeps free lists of each size.  Blocks that
  1626. X * don't exactly fit are passed up to the next larger size.  In this 
  1627. X * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long.
  1628. X * This is designed for use in a program that uses vast quantities of memory,
  1629. X * but bombs when it runs out. 
  1630. X */
  1631. X
  1632. X#include "EXTERN.h"
  1633. X#include "perl.h"
  1634. X
  1635. Xstatic findbucket(), morecore();
  1636. X
  1637. X/* I don't much care whether these are defined in sys/types.h--LAW */
  1638. X
  1639. X#define u_char unsigned char
  1640. X#define u_int unsigned int
  1641. X#define u_short unsigned short
  1642. X
  1643. X/*
  1644. X * The overhead on a block is at least 4 bytes.  When free, this space
  1645. X * contains a pointer to the next free block, and the bottom two bits must
  1646. X * be zero.  When in use, the first byte is set to MAGIC, and the second
  1647. X * byte is the size index.  The remaining bytes are for alignment.
  1648. X * If range checking is enabled and the size of the block fits
  1649. X * in two bytes, then the top two bytes hold the size of the requested block
  1650. X * plus the range checking words, and the header word MINUS ONE.
  1651. X */
  1652. Xunion    overhead {
  1653. X    union    overhead *ov_next;    /* when free */
  1654. X#if ALIGNBYTES > 4
  1655. X    double    strut;            /* alignment problems */
  1656. X#endif
  1657. X    struct {
  1658. X        u_char    ovu_magic;    /* magic number */
  1659. X        u_char    ovu_index;    /* bucket # */
  1660. X#ifdef RCHECK
  1661. X        u_short    ovu_size;    /* actual block size */
  1662. X        u_int    ovu_rmagic;    /* range magic number */
  1663. X#endif
  1664. X    } ovu;
  1665. X#define    ov_magic    ovu.ovu_magic
  1666. X#define    ov_index    ovu.ovu_index
  1667. X#define    ov_size        ovu.ovu_size
  1668. X#define    ov_rmagic    ovu.ovu_rmagic
  1669. X};
  1670. X
  1671. X#define    MAGIC        0xff        /* magic # on accounting info */
  1672. X#define OLDMAGIC    0x7f        /* same after a free() */
  1673. X#define RMAGIC        0x55555555    /* magic # on range info */
  1674. X#ifdef RCHECK
  1675. X#define    RSLOP        sizeof (u_int)
  1676. X#else
  1677. X#define    RSLOP        0
  1678. X#endif
  1679. X
  1680. X/*
  1681. X * nextf[i] is the pointer to the next free block of size 2^(i+3).  The
  1682. X * smallest allocatable block is 8 bytes.  The overhead information
  1683. X * precedes the data area returned to the user.
  1684. X */
  1685. X#define    NBUCKETS 30
  1686. Xstatic    union overhead *nextf[NBUCKETS];
  1687. Xextern    char *sbrk();
  1688. X
  1689. X#ifdef MSTATS
  1690. X/*
  1691. X * nmalloc[i] is the difference between the number of mallocs and frees
  1692. X * for a given block size.
  1693. X */
  1694. Xstatic    u_int nmalloc[NBUCKETS];
  1695. X#include <stdio.h>
  1696. X#endif
  1697. X
  1698. X#ifdef debug
  1699. X#define    ASSERT(p)   if (!(p)) botch("p"); else
  1700. Xstatic
  1701. Xbotch(s)
  1702. X    char *s;
  1703. X{
  1704. X
  1705. X    printf("assertion botched: %s\n", s);
  1706. X    abort();
  1707. X}
  1708. X#else
  1709. X#define    ASSERT(p)
  1710. X#endif
  1711. X
  1712. XMALLOCPTRTYPE *
  1713. Xmalloc(nbytes)
  1714. X    register unsigned nbytes;
  1715. X{
  1716. X      register union overhead *p;
  1717. X      register int bucket = 0;
  1718. X      register unsigned shiftr;
  1719. X
  1720. X    /*
  1721. X     * Convert amount of memory requested into
  1722. X     * closest block size stored in hash buckets
  1723. X     * which satisfies request.  Account for
  1724. X     * space used per block for accounting.
  1725. X     */
  1726. X      nbytes += sizeof (union overhead) + RSLOP;
  1727. X      nbytes = (nbytes + 3) &~ 3; 
  1728. X      shiftr = (nbytes - 1) >> 2;
  1729. X    /* apart from this loop, this is O(1) */
  1730. X      while (shiftr >>= 1)
  1731. X          bucket++;
  1732. X    /*
  1733. X     * If nothing in hash bucket right now,
  1734. X     * request more memory from the system.
  1735. X     */
  1736. X      if (nextf[bucket] == NULL)    
  1737. X          morecore(bucket);
  1738. X      if ((p = (union overhead *)nextf[bucket]) == NULL)
  1739. X          return (NULL);
  1740. X    /* remove from linked list */
  1741. X#ifdef RCHECK
  1742. X    if (*((int*)p) & (sizeof(union overhead) - 1))
  1743. X#ifndef I286
  1744. X        fprintf(stderr,"Corrupt malloc ptr 0x%x at 0x%x\n",*((int*)p),p);
  1745. X#else
  1746. X        fprintf(stderr,"Corrupt malloc ptr 0x%lx at 0x%lx\n",*((int*)p),p);
  1747. X#endif
  1748. X#endif
  1749. X      nextf[bucket] = p->ov_next;
  1750. X    p->ov_magic = MAGIC;
  1751. X    p->ov_index= bucket;
  1752. X#ifdef MSTATS
  1753. X      nmalloc[bucket]++;
  1754. X#endif
  1755. X#ifdef RCHECK
  1756. X    /*
  1757. X     * Record allocated size of block and
  1758. X     * bound space with magic numbers.
  1759. X     */
  1760. X      if (nbytes <= 0x10000)
  1761. X        p->ov_size = nbytes - 1;
  1762. X    p->ov_rmagic = RMAGIC;
  1763. X      *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
  1764. X#endif
  1765. X      return ((char *)(p + 1));
  1766. X}
  1767. X
  1768. X/*
  1769. X * Allocate more memory to the indicated bucket.
  1770. X */
  1771. Xstatic
  1772. Xmorecore(bucket)
  1773. X    register int bucket;
  1774. X{
  1775. X      register union overhead *op;
  1776. X      register int rnu;       /* 2^rnu bytes will be requested */
  1777. X      register int nblks;     /* become nblks blocks of the desired size */
  1778. X    register int siz;
  1779. X
  1780. X      if (nextf[bucket])
  1781. X          return;
  1782. X    /*
  1783. X     * Insure memory is allocated
  1784. X     * on a page boundary.  Should
  1785. X     * make getpageize call?
  1786. X     */
  1787. X      op = (union overhead *)sbrk(0);
  1788. X#ifndef I286
  1789. X      if ((int)op & 0x3ff)
  1790. X          (void)sbrk(1024 - ((int)op & 0x3ff));
  1791. X#else
  1792. X    /* The sbrk(0) call on the I286 always returns the next segment */
  1793. X#endif
  1794. X
  1795. X#ifndef I286
  1796. X    /* take 2k unless the block is bigger than that */
  1797. X      rnu = (bucket <= 8) ? 11 : bucket + 3;
  1798. X#else
  1799. X    /* take 16k unless the block is bigger than that 
  1800. X       (80286s like large segments!)        */
  1801. X      rnu = (bucket <= 11) ? 14 : bucket + 3;
  1802. X#endif
  1803. X      nblks = 1 << (rnu - (bucket + 3));  /* how many blocks to get */
  1804. X      if (rnu < bucket)
  1805. X        rnu = bucket;
  1806. X    op = (union overhead *)sbrk(1 << rnu);
  1807. X    /* no more room! */
  1808. X      if ((int)op == -1)
  1809. X          return;
  1810. X    /*
  1811. X     * Round up to minimum allocation size boundary
  1812. X     * and deduct from block count to reflect.
  1813. X     */
  1814. X#ifndef I286
  1815. X      if ((int)op & 7) {
  1816. X          op = (union overhead *)(((int)op + 8) &~ 7);
  1817. X          nblks--;
  1818. X      }
  1819. X#else
  1820. X    /* Again, this should always be ok on an 80286 */
  1821. X#endif
  1822. X    /*
  1823. X     * Add new memory allocated to that on
  1824. X     * free list for this hash bucket.
  1825. X     */
  1826. X      nextf[bucket] = op;
  1827. X      siz = 1 << (bucket + 3);
  1828. X      while (--nblks > 0) {
  1829. X        op->ov_next = (union overhead *)((caddr_t)op + siz);
  1830. X        op = (union overhead *)((caddr_t)op + siz);
  1831. X      }
  1832. X}
  1833. X
  1834. Xvoid
  1835. Xfree(cp)
  1836. X    char *cp;
  1837. X{   
  1838. X      register int size;
  1839. X    register union overhead *op;
  1840. X
  1841. X      if (cp == NULL)
  1842. X          return;
  1843. X    op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
  1844. X#ifdef debug
  1845. X      ASSERT(op->ov_magic == MAGIC);        /* make sure it was in use */
  1846. X#else
  1847. X    if (op->ov_magic != MAGIC) {
  1848. X        warn("%s free() ignored",
  1849. X            op->ov_magic == OLDMAGIC ? "Duplicate" : "Bad");
  1850. X        return;                /* sanity */
  1851. X    }
  1852. X    op->ov_magic = OLDMAGIC;
  1853. X#endif
  1854. X#ifdef RCHECK
  1855. X      ASSERT(op->ov_rmagic == RMAGIC);
  1856. X    if (op->ov_index <= 13)
  1857. X        ASSERT(*(u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP) == RMAGIC);
  1858. X#endif
  1859. X      ASSERT(op->ov_index < NBUCKETS);
  1860. X      size = op->ov_index;
  1861. X    op->ov_next = nextf[size];
  1862. X      nextf[size] = op;
  1863. X#ifdef MSTATS
  1864. X      nmalloc[size]--;
  1865. X#endif
  1866. X}
  1867. X
  1868. X/*
  1869. X * When a program attempts "storage compaction" as mentioned in the
  1870. X * old malloc man page, it realloc's an already freed block.  Usually
  1871. X * this is the last block it freed; occasionally it might be farther
  1872. X * back.  We have to search all the free lists for the block in order
  1873. X * to determine its bucket: 1st we make one pass thru the lists
  1874. X * checking only the first block in each; if that fails we search
  1875. X * ``reall_srchlen'' blocks in each list for a match (the variable
  1876. X * is extern so the caller can modify it).  If that fails we just copy
  1877. X * however many bytes was given to realloc() and hope it's not huge.
  1878. X */
  1879. Xint reall_srchlen = 4;    /* 4 should be plenty, -1 =>'s whole list */
  1880. X
  1881. XMALLOCPTRTYPE *
  1882. Xrealloc(cp, nbytes)
  1883. X    char *cp; 
  1884. X    unsigned nbytes;
  1885. X{   
  1886. X      register u_int onb;
  1887. X    union overhead *op;
  1888. X      char *res;
  1889. X    register int i;
  1890. X    int was_alloced = 0;
  1891. X
  1892. X      if (cp == NULL)
  1893. X          return (malloc(nbytes));
  1894. X    op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
  1895. X    if (op->ov_magic == MAGIC) {
  1896. X        was_alloced++;
  1897. X        i = op->ov_index;
  1898. X    } else {
  1899. X        /*
  1900. X         * Already free, doing "compaction".
  1901. X         *
  1902. X         * Search for the old block of memory on the
  1903. X         * free list.  First, check the most common
  1904. X         * case (last element free'd), then (this failing)
  1905. X         * the last ``reall_srchlen'' items free'd.
  1906. X         * If all lookups fail, then assume the size of
  1907. X         * the memory block being realloc'd is the
  1908. X         * smallest possible.
  1909. X         */
  1910. X        if ((i = findbucket(op, 1)) < 0 &&
  1911. X            (i = findbucket(op, reall_srchlen)) < 0)
  1912. X            i = 0;
  1913. X    }
  1914. X    onb = (1 << (i + 3)) - sizeof (*op) - RSLOP;
  1915. X    /* avoid the copy if same size block */
  1916. X    if (was_alloced &&
  1917. X        nbytes <= onb && nbytes > (onb >> 1) - sizeof(*op) - RSLOP) {
  1918. X#ifdef RCHECK
  1919. X        /*
  1920. X         * Record new allocated size of block and
  1921. X         * bound space with magic numbers.
  1922. X         */
  1923. X        if (op->ov_index <= 13) {
  1924. X            /*
  1925. X             * Convert amount of memory requested into
  1926. X             * closest block size stored in hash buckets
  1927. X             * which satisfies request.  Account for
  1928. X             * space used per block for accounting.
  1929. X             */
  1930. X            nbytes += sizeof (union overhead) + RSLOP;
  1931. X            nbytes = (nbytes + 3) &~ 3; 
  1932. X            op->ov_size = nbytes - 1;
  1933. X            *((u_int *)((caddr_t)op + nbytes - RSLOP)) = RMAGIC;
  1934. X        }
  1935. X#endif
  1936. X        return(cp);
  1937. X    }
  1938. X      if ((res = malloc(nbytes)) == NULL)
  1939. X          return (NULL);
  1940. X      if (cp != res)            /* common optimization */
  1941. X        (void)bcopy(cp, res, (int)((nbytes < onb) ? nbytes : onb));
  1942. X      if (was_alloced)
  1943. X        free(cp);
  1944. X      return (res);
  1945. X}
  1946. X
  1947. X/*
  1948. X * Search ``srchlen'' elements of each free list for a block whose
  1949. X * header starts at ``freep''.  If srchlen is -1 search the whole list.
  1950. X * Return bucket number, or -1 if not found.
  1951. X */
  1952. Xstatic
  1953. Xfindbucket(freep, srchlen)
  1954. X    union overhead *freep;
  1955. X    int srchlen;
  1956. X{
  1957. X    register union overhead *p;
  1958. X    register int i, j;
  1959. X
  1960. X    for (i = 0; i < NBUCKETS; i++) {
  1961. X        j = 0;
  1962. X        for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
  1963. X            if (p == freep)
  1964. X                return (i);
  1965. X            j++;
  1966. X        }
  1967. X    }
  1968. X    return (-1);
  1969. X}
  1970. X
  1971. X#ifdef MSTATS
  1972. X/*
  1973. X * mstats - print out statistics about malloc
  1974. X * 
  1975. X * Prints two lines of numbers, one showing the length of the free list
  1976. X * for each size category, the second showing the number of mallocs -
  1977. X * frees for each size category.
  1978. X */
  1979. Xmstats(s)
  1980. X    char *s;
  1981. X{
  1982. X      register int i, j;
  1983. X      register union overhead *p;
  1984. X      int totfree = 0,
  1985. X      totused = 0;
  1986. X
  1987. X      fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s);
  1988. X      for (i = 0; i < NBUCKETS; i++) {
  1989. X          for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
  1990. X              ;
  1991. X          fprintf(stderr, " %d", j);
  1992. X          totfree += j * (1 << (i + 3));
  1993. X      }
  1994. X      fprintf(stderr, "\nused:\t");
  1995. X      for (i = 0; i < NBUCKETS; i++) {
  1996. X          fprintf(stderr, " %d", nmalloc[i]);
  1997. X          totused += nmalloc[i] * (1 << (i + 3));
  1998. X      }
  1999. X      fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n",
  2000. X        totused, totfree);
  2001. X}
  2002. X#endif
  2003. X#endif /* lint */
  2004. !STUFFY!FUNK!
  2005. echo Extracting t/op/fork.t
  2006. sed >t/op/fork.t <<'!STUFFY!FUNK!' -e 's/X//'
  2007. X#!./perl
  2008. X
  2009. X# $Header: fork.t,v 4.0 91/03/20 01:52:43 lwall Locked $
  2010. X
  2011. X$| = 1;
  2012. Xprint "1..2\n";
  2013. X
  2014. Xif ($cid = fork) {
  2015. X    sleep 2;
  2016. X    if ($result = (kill 9, $cid)) {print "ok 2\n";} else {print "not ok 2 $result\n";}
  2017. X}
  2018. Xelse {
  2019. X    $| = 1;
  2020. X    print "ok 1\n";
  2021. X    sleep 10;
  2022. X}
  2023. !STUFFY!FUNK!
  2024. echo " "
  2025. echo "End of kit 12 (of 36)"
  2026. cat /dev/null >kit12isdone
  2027. run=''
  2028. config=''
  2029. for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36; do
  2030.     if test -f kit${iskit}isdone; then
  2031.     run="$run $iskit"
  2032.     else
  2033.     todo="$todo $iskit"
  2034.     fi
  2035. done
  2036. case $todo in
  2037.     '')
  2038.     echo "You have run all your kits.  Please read README and then type Configure."
  2039.     for combo in *:AA; do
  2040.         if test -f "$combo"; then
  2041.         realfile=`basename $combo :AA`
  2042.         cat $realfile:[A-Z][A-Z] >$realfile
  2043.         rm -rf $realfile:[A-Z][A-Z]
  2044.         fi
  2045.     done
  2046.     rm -rf kit*isdone
  2047.     chmod 755 Configure
  2048.     ;;
  2049.     *)  echo "You have run$run."
  2050.     echo "You still need to run$todo."
  2051.     ;;
  2052. esac
  2053. : Someone might mail this, so...
  2054. exit
  2055.  
  2056. exit 0 # Just in case...
  2057. -- 
  2058. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2059. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2060. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2061. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2062.