home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume20 / perl3.0 / part15 < prev    next >
Text File  |  1989-11-01  |  50KB  |  1,941 lines

  1. Subject:  v20i098:  Perl, a language with features of C/sed/awk/shell/etc, Part15/24
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Larry Wall <lwall@jpl-devvax.jpl.nasa.gov>
  7. Posting-number: Volume 20, Issue 98
  8. Archive-name: perl3.0/part15
  9.  
  10. #! /bin/sh
  11.  
  12. # Make a new directory for the perl sources, cd to it, and run kits 1
  13. # thru 24 through sh.  When all 24 kits have been run, read README.
  14.  
  15. echo "This is perl 3.0 kit 15 (of 24).  If kit 15 is complete, the line"
  16. echo '"'"End of kit 15 (of 24)"'" will echo at the end.'
  17. echo ""
  18. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  19. mkdir t x2p 2>/dev/null
  20. echo Extracting cmd.c
  21. sed >cmd.c <<'!STUFFY!FUNK!' -e 's/X//'
  22. X/* $Header: cmd.c,v 3.0 89/10/18 15:09:02 lwall Locked $
  23. X *
  24. X *    Copyright (c) 1989, Larry Wall
  25. X *
  26. X *    You may distribute under the terms of the GNU General Public License
  27. X *    as specified in the README file that comes with the perl 3.0 kit.
  28. X *
  29. X * $Log:    cmd.c,v $
  30. X * Revision 3.0  89/10/18  15:09:02  lwall
  31. X * 3.0 baseline
  32. X * 
  33. X */
  34. X
  35. X#include "EXTERN.h"
  36. X#include "perl.h"
  37. X
  38. X#ifdef I_VARARGS
  39. X#  include <varargs.h>
  40. X#endif
  41. X
  42. Xstatic STR str_chop;
  43. X
  44. Xvoid grow_dlevel();
  45. X
  46. X/* This is the main command loop.  We try to spend as much time in this loop
  47. X * as possible, so lots of optimizations do their activities in here.  This
  48. X * means things get a little sloppy.
  49. X */
  50. X
  51. Xint
  52. Xcmd_exec(cmd,gimme,sp)
  53. X#ifdef cray    /* nobody else has complained yet */
  54. XCMD *cmd;
  55. X#else
  56. Xregister CMD *cmd;
  57. X#endif
  58. Xint gimme;
  59. Xint sp;
  60. X{
  61. X    SPAT *oldspat;
  62. X    int oldsave;
  63. X    int aryoptsave;
  64. X#ifdef DEBUGGING
  65. X    int olddlevel;
  66. X    int entdlevel;
  67. X#endif
  68. X    register STR *retstr = &str_undef;
  69. X    register char *tmps;
  70. X    register int cmdflags;
  71. X    register int match;
  72. X    register char *go_to = goto_targ;
  73. X    register int newsp = -2;
  74. X    register STR **st = stack->ary_array;
  75. X    FILE *fp;
  76. X    ARRAY *ar;
  77. X
  78. X    lastsize = 0;
  79. X#ifdef DEBUGGING
  80. X    entdlevel = dlevel;
  81. X#endif
  82. Xtail_recursion_entry:
  83. X#ifdef DEBUGGING
  84. X    dlevel = entdlevel;
  85. X#endif
  86. X#ifdef TAINT
  87. X    tainted = 0;    /* Each statement is presumed innocent */
  88. X#endif
  89. X    if (cmd == Nullcmd) {
  90. X    if (gimme == G_ARRAY && newsp > -2)
  91. X        return newsp;
  92. X    else {
  93. X        st[++sp] = retstr;
  94. X        return sp;
  95. X    }
  96. X    }
  97. X    cmdflags = cmd->c_flags;    /* hopefully load register */
  98. X    if (go_to) {
  99. X    if (cmd->c_label && strEQ(go_to,cmd->c_label))
  100. X        goto_targ = go_to = Nullch;        /* here at last */
  101. X    else {
  102. X        switch (cmd->c_type) {
  103. X        case C_IF:
  104. X        oldspat = curspat;
  105. X        oldsave = savestack->ary_fill;
  106. X#ifdef DEBUGGING
  107. X        olddlevel = dlevel;
  108. X#endif
  109. X        retstr = &str_yes;
  110. X        newsp = -2;
  111. X        if (cmd->ucmd.ccmd.cc_true) {
  112. X#ifdef DEBUGGING
  113. X            if (debug) {
  114. X            debname[dlevel] = 't';
  115. X            debdelim[dlevel] = '_';
  116. X            if (++dlevel >= dlmax)
  117. X                grow_dlevel();
  118. X            }
  119. X#endif
  120. X            newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
  121. X            st = stack->ary_array;    /* possibly reallocated */
  122. X            retstr = st[newsp];
  123. X        }
  124. X        if (!goto_targ)
  125. X            go_to = Nullch;
  126. X        curspat = oldspat;
  127. X        if (savestack->ary_fill > oldsave)
  128. X            restorelist(oldsave);
  129. X#ifdef DEBUGGING
  130. X        dlevel = olddlevel;
  131. X#endif
  132. X        cmd = cmd->ucmd.ccmd.cc_alt;
  133. X        goto tail_recursion_entry;
  134. X        case C_ELSE:
  135. X        oldspat = curspat;
  136. X        oldsave = savestack->ary_fill;
  137. X#ifdef DEBUGGING
  138. X        olddlevel = dlevel;
  139. X#endif
  140. X        retstr = &str_undef;
  141. X        newsp = -2;
  142. X        if (cmd->ucmd.ccmd.cc_true) {
  143. X#ifdef DEBUGGING
  144. X            if (debug) {
  145. X            debname[dlevel] = 'e';
  146. X            debdelim[dlevel] = '_';
  147. X            if (++dlevel >= dlmax)
  148. X                grow_dlevel();
  149. X            }
  150. X#endif
  151. X            newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
  152. X            st = stack->ary_array;    /* possibly reallocated */
  153. X            retstr = st[newsp];
  154. X        }
  155. X        if (!goto_targ)
  156. X            go_to = Nullch;
  157. X        curspat = oldspat;
  158. X        if (savestack->ary_fill > oldsave)
  159. X            restorelist(oldsave);
  160. X#ifdef DEBUGGING
  161. X        dlevel = olddlevel;
  162. X#endif
  163. X        break;
  164. X        case C_BLOCK:
  165. X        case C_WHILE:
  166. X        if (!(cmdflags & CF_ONCE)) {
  167. X            cmdflags |= CF_ONCE;
  168. X            if (++loop_ptr >= loop_max) {
  169. X            loop_max += 128;
  170. X            Renew(loop_stack, loop_max, struct loop);
  171. X            }
  172. X            loop_stack[loop_ptr].loop_label = cmd->c_label;
  173. X            loop_stack[loop_ptr].loop_sp = sp;
  174. X#ifdef DEBUGGING
  175. X            if (debug & 4) {
  176. X            deb("(Pushing label #%d %s)\n",
  177. X              loop_ptr, cmd->c_label ? cmd->c_label : "");
  178. X            }
  179. X#endif
  180. X        }
  181. X        switch (setjmp(loop_stack[loop_ptr].loop_env)) {
  182. X        case O_LAST:    /* not done unless go_to found */
  183. X            go_to = Nullch;
  184. X            st = stack->ary_array;    /* possibly reallocated */
  185. X            if (lastretstr) {
  186. X            retstr = lastretstr;
  187. X            newsp = -2;
  188. X            }
  189. X            else {
  190. X            newsp = sp + lastsize;
  191. X            retstr = st[newsp];
  192. X            }
  193. X#ifdef DEBUGGING
  194. X            olddlevel = dlevel;
  195. X#endif
  196. X            curspat = oldspat;
  197. X            if (savestack->ary_fill > oldsave)
  198. X            restorelist(oldsave);
  199. X            goto next_cmd;
  200. X        case O_NEXT:    /* not done unless go_to found */
  201. X            go_to = Nullch;
  202. X            goto next_iter;
  203. X        case O_REDO:    /* not done unless go_to found */
  204. X            go_to = Nullch;
  205. X            goto doit;
  206. X        }
  207. X        oldspat = curspat;
  208. X        oldsave = savestack->ary_fill;
  209. X#ifdef DEBUGGING
  210. X        olddlevel = dlevel;
  211. X#endif
  212. X        if (cmd->ucmd.ccmd.cc_true) {
  213. X#ifdef DEBUGGING
  214. X            if (debug) {
  215. X            debname[dlevel] = 't';
  216. X            debdelim[dlevel] = '_';
  217. X            if (++dlevel >= dlmax)
  218. X                grow_dlevel();
  219. X            }
  220. X#endif
  221. X            newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
  222. X            st = stack->ary_array;    /* possibly reallocated */
  223. X            retstr = st[newsp];
  224. X        }
  225. X        if (!goto_targ) {
  226. X            go_to = Nullch;
  227. X            goto next_iter;
  228. X        }
  229. X#ifdef DEBUGGING
  230. X        dlevel = olddlevel;
  231. X#endif
  232. X        if (cmd->ucmd.ccmd.cc_alt) {
  233. X#ifdef DEBUGGING
  234. X            if (debug) {
  235. X            debname[dlevel] = 'a';
  236. X            debdelim[dlevel] = '_';
  237. X            if (++dlevel >= dlmax)
  238. X                grow_dlevel();
  239. X            }
  240. X#endif
  241. X            newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme,sp);
  242. X            st = stack->ary_array;    /* possibly reallocated */
  243. X            retstr = st[newsp];
  244. X        }
  245. X        if (goto_targ)
  246. X            break;
  247. X        go_to = Nullch;
  248. X        goto finish_while;
  249. X        }
  250. X        cmd = cmd->c_next;
  251. X        if (cmd && cmd->c_head == cmd)
  252. X                    /* reached end of while loop */
  253. X        return sp;        /* targ isn't in this block */
  254. X        if (cmdflags & CF_ONCE) {
  255. X#ifdef DEBUGGING
  256. X        if (debug & 4) {
  257. X            tmps = loop_stack[loop_ptr].loop_label;
  258. X            deb("(Popping label #%d %s)\n",loop_ptr,
  259. X            tmps ? tmps : "" );
  260. X        }
  261. X#endif
  262. X        loop_ptr--;
  263. X        }
  264. X        goto tail_recursion_entry;
  265. X    }
  266. X    }
  267. X
  268. Xuntil_loop:
  269. X
  270. X    /* Set line number so run-time errors can be located */
  271. X
  272. X    line = cmd->c_line;
  273. X
  274. X#ifdef DEBUGGING
  275. X    if (debug) {
  276. X    if (debug & 2) {
  277. X        deb("%s    (%lx)    r%lx    t%lx    a%lx    n%lx    cs%lx\n",
  278. X        cmdname[cmd->c_type],cmd,cmd->c_expr,
  279. X        cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,
  280. X        curspat);
  281. X    }
  282. X    debname[dlevel] = cmdname[cmd->c_type][0];
  283. X    debdelim[dlevel] = '!';
  284. X    if (++dlevel >= dlmax)
  285. X        grow_dlevel();
  286. X    }
  287. X#endif
  288. X
  289. X    /* Here is some common optimization */
  290. X
  291. X    if (cmdflags & CF_COND) {
  292. X    switch (cmdflags & CF_OPTIMIZE) {
  293. X
  294. X    case CFT_FALSE:
  295. X        retstr = cmd->c_short;
  296. X        newsp = -2;
  297. X        match = FALSE;
  298. X        if (cmdflags & CF_NESURE)
  299. X        goto maybe;
  300. X        break;
  301. X    case CFT_TRUE:
  302. X        retstr = cmd->c_short;
  303. X        newsp = -2;
  304. X        match = TRUE;
  305. X        if (cmdflags & CF_EQSURE)
  306. X        goto flipmaybe;
  307. X        break;
  308. X
  309. X    case CFT_REG:
  310. X        retstr = STAB_STR(cmd->c_stab);
  311. X        newsp = -2;
  312. X        match = str_true(retstr);    /* => retstr = retstr, c2 should fix */
  313. X        if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
  314. X        goto flipmaybe;
  315. X        break;
  316. X
  317. X    case CFT_ANCHOR:    /* /^pat/ optimization */
  318. X        if (multiline) {
  319. X        if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE))
  320. X            goto scanner;    /* just unanchor it */
  321. X        else
  322. X            break;        /* must evaluate */
  323. X        }
  324. X        /* FALL THROUGH */
  325. X    case CFT_STROP:        /* string op optimization */
  326. X        retstr = STAB_STR(cmd->c_stab);
  327. X        newsp = -2;
  328. X#ifndef I286
  329. X        if (*cmd->c_short->str_ptr == *str_get(retstr) &&
  330. X            bcmp(cmd->c_short->str_ptr, str_get(retstr),
  331. X              cmd->c_slen) == 0 ) {
  332. X        if (cmdflags & CF_EQSURE) {
  333. X            if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
  334. X            curspat = Nullspat;
  335. X            if (leftstab)
  336. X                str_nset(stab_val(leftstab),"",0);
  337. X            if (amperstab)
  338. X                str_sset(stab_val(amperstab),cmd->c_short);
  339. X            if (rightstab)
  340. X                str_nset(stab_val(rightstab),
  341. X                  retstr->str_ptr + cmd->c_slen,
  342. X                  retstr->str_cur - cmd->c_slen);
  343. X            }
  344. X            match = !(cmdflags & CF_FIRSTNEG);
  345. X            retstr = &str_yes;
  346. X            goto flipmaybe;
  347. X        }
  348. X        }
  349. X        else if (cmdflags & CF_NESURE) {
  350. X        match = cmdflags & CF_FIRSTNEG;
  351. X        retstr = &str_no;
  352. X        goto flipmaybe;
  353. X        }
  354. X#else
  355. X        {
  356. X        char *zap1, *zap2, zap1c, zap2c;
  357. X        int  zaplen;
  358. X
  359. X        zap1 = cmd->c_short->str_ptr;
  360. X        zap2 = str_get(retstr);
  361. X        zap1c = *zap1;
  362. X        zap2c = *zap2;
  363. X        zaplen = cmd->c_slen;
  364. X        if ((zap1c == zap2c) && (bcmp(zap1, zap2, zaplen) == 0)) {
  365. X            if (cmdflags & CF_EQSURE) {
  366. X            if (sawampersand &&
  367. X              (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
  368. X                curspat = Nullspat;
  369. X                if (leftstab)
  370. X                str_nset(stab_val(leftstab),"",0);
  371. X                if (amperstab)
  372. X                str_sset(stab_val(amperstab),cmd->c_short);
  373. X                if (rightstab)
  374. X                str_nset(stab_val(rightstab),
  375. X                     retstr->str_ptr + cmd->c_slen,
  376. X                     retstr->str_cur - cmd->c_slen);
  377. X            }
  378. X             match = !(cmdflags & CF_FIRSTNEG);
  379. X             retstr = &str_yes;
  380. X             goto flipmaybe;
  381. X            }
  382. X        }
  383. X        else if (cmdflags & CF_NESURE) {
  384. X            match = cmdflags & CF_FIRSTNEG;
  385. X            retstr = &str_no;
  386. X            goto flipmaybe;
  387. X        }
  388. X        }
  389. X#endif
  390. X        break;            /* must evaluate */
  391. X
  392. X    case CFT_SCAN:            /* non-anchored search */
  393. X      scanner:
  394. X        retstr = STAB_STR(cmd->c_stab);
  395. X        newsp = -2;
  396. X        if (retstr->str_pok & SP_STUDIED)
  397. X        if (screamfirst[cmd->c_short->str_rare] >= 0)
  398. X            tmps = screaminstr(retstr, cmd->c_short);
  399. X        else
  400. X            tmps = Nullch;
  401. X        else {
  402. X        tmps = str_get(retstr);        /* make sure it's pok */
  403. X#ifndef lint
  404. X        tmps = fbminstr((unsigned char*)tmps,
  405. X            (unsigned char*)tmps + retstr->str_cur, cmd->c_short);
  406. X#endif
  407. X        }
  408. X        if (tmps) {
  409. X        if (cmdflags & CF_EQSURE) {
  410. X            ++cmd->c_short->str_u.str_useful;
  411. X            if (sawampersand) {
  412. X            curspat = Nullspat;
  413. X            if (leftstab)
  414. X                str_nset(stab_val(leftstab),retstr->str_ptr,
  415. X                  tmps - retstr->str_ptr);
  416. X            if (amperstab)
  417. X                str_sset(stab_val(amperstab),cmd->c_short);
  418. X            if (rightstab)
  419. X                str_nset(stab_val(rightstab),
  420. X                  tmps + cmd->c_short->str_cur,
  421. X                  retstr->str_cur - (tmps - retstr->str_ptr) -
  422. X                cmd->c_short->str_cur);
  423. X            }
  424. X            match = !(cmdflags & CF_FIRSTNEG);
  425. X            retstr = &str_yes;
  426. X            goto flipmaybe;
  427. X        }
  428. X        else
  429. X            hint = tmps;
  430. X        }
  431. X        else {
  432. X        if (cmdflags & CF_NESURE) {
  433. X            ++cmd->c_short->str_u.str_useful;
  434. X            match = cmdflags & CF_FIRSTNEG;
  435. X            retstr = &str_no;
  436. X            goto flipmaybe;
  437. X        }
  438. X        }
  439. X        if (--cmd->c_short->str_u.str_useful < 0) {
  440. X        str_free(cmd->c_short);
  441. X        cmd->c_short = Nullstr;
  442. X        cmdflags &= ~CF_OPTIMIZE;
  443. X        cmdflags |= CFT_EVAL;    /* never try this optimization again */
  444. X        cmd->c_flags = cmdflags;
  445. X        }
  446. X        break;            /* must evaluate */
  447. X
  448. X    case CFT_NUMOP:        /* numeric op optimization */
  449. X        retstr = STAB_STR(cmd->c_stab);
  450. X        newsp = -2;
  451. X        switch (cmd->c_slen) {
  452. X        case O_EQ:
  453. X        if (dowarn) {
  454. X            if ((!retstr->str_nok && !looks_like_number(retstr)))
  455. X            warn("Possible use of == on string value");
  456. X        }
  457. X        match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval);
  458. X        break;
  459. X        case O_NE:
  460. X        match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval);
  461. X        break;
  462. X        case O_LT:
  463. X        match = (str_gnum(retstr) <  cmd->c_short->str_u.str_nval);
  464. X        break;
  465. X        case O_LE:
  466. X        match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval);
  467. X        break;
  468. X        case O_GT:
  469. X        match = (str_gnum(retstr) >  cmd->c_short->str_u.str_nval);
  470. X        break;
  471. X        case O_GE:
  472. X        match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval);
  473. X        break;
  474. X        }
  475. X        if (match) {
  476. X        if (cmdflags & CF_EQSURE) {
  477. X            retstr = &str_yes;
  478. X            goto flipmaybe;
  479. X        }
  480. X        }
  481. X        else if (cmdflags & CF_NESURE) {
  482. X        retstr = &str_no;
  483. X        goto flipmaybe;
  484. X        }
  485. X        break;            /* must evaluate */
  486. X
  487. X    case CFT_INDGETS:        /* while (<$foo>) */
  488. X        last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE);
  489. X        if (!stab_io(last_in_stab))
  490. X        stab_io(last_in_stab) = stio_new();
  491. X        goto dogets;
  492. X    case CFT_GETS:            /* really a while (<file>) */
  493. X        last_in_stab = cmd->c_stab;
  494. X      dogets:
  495. X        fp = stab_io(last_in_stab)->ifp;
  496. X        retstr = stab_val(defstab);
  497. X        newsp = -2;
  498. X        if (fp && str_gets(retstr, fp, 0)) {
  499. X        if (*retstr->str_ptr == '0' && retstr->str_cur == 1)
  500. X            match = FALSE;
  501. X        else
  502. X            match = TRUE;
  503. X        stab_io(last_in_stab)->lines++;
  504. X        }
  505. X        else if (stab_io(last_in_stab)->flags & IOF_ARGV)
  506. X        goto doeval;    /* doesn't necessarily count as EOF yet */
  507. X        else {
  508. X        retstr = &str_undef;
  509. X        match = FALSE;
  510. X        }
  511. X        goto flipmaybe;
  512. X    case CFT_EVAL:
  513. X        break;
  514. X    case CFT_UNFLIP:
  515. X        while (tmps_max > tmps_base)    /* clean up after last eval */
  516. X        str_free(tmps_list[tmps_max--]);
  517. X        newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
  518. X        st = stack->ary_array;    /* possibly reallocated */
  519. X        retstr = st[newsp];
  520. X        match = str_true(retstr);
  521. X        if (cmd->c_expr->arg_type == O_FLIP)    /* undid itself? */
  522. X        cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  523. X        goto maybe;
  524. X    case CFT_CHOP:
  525. X        retstr = stab_val(cmd->c_stab);
  526. X        newsp = -2;
  527. X        match = (retstr->str_cur != 0);
  528. X        tmps = str_get(retstr);
  529. X        tmps += retstr->str_cur - match;
  530. X        str_nset(&str_chop,tmps,match);
  531. X        *tmps = '\0';
  532. X        retstr->str_nok = 0;
  533. X        retstr->str_cur = tmps - retstr->str_ptr;
  534. X        retstr = &str_chop;
  535. X        goto flipmaybe;
  536. X    case CFT_ARRAY:
  537. X        ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab);
  538. X        match = ar->ary_index;    /* just to get register */
  539. X
  540. X        if (match < 0) {        /* first time through here? */
  541. X        aryoptsave = savestack->ary_fill;
  542. X        savesptr(&stab_val(cmd->c_stab));
  543. X        saveint(&ar->ary_index);
  544. X        }
  545. X
  546. X        if (match >= ar->ary_fill) {    /* we're in LAST, probably */
  547. X        retstr = &str_undef;
  548. X        ar->ary_index = -1;    /* this is actually redundant */
  549. X        match = FALSE;
  550. X        }
  551. X        else {
  552. X        match++;
  553. X        retstr = stab_val(cmd->c_stab) = ar->ary_array[match];
  554. X        ar->ary_index = match;
  555. X        match = TRUE;
  556. X        }
  557. X        newsp = -2;
  558. X        goto maybe;
  559. X    }
  560. X
  561. X    /* we have tried to make this normal case as abnormal as possible */
  562. X
  563. X    doeval:
  564. X    if (gimme == G_ARRAY) {
  565. X        lastretstr = Nullstr;
  566. X        lastspbase = sp;
  567. X        lastsize = newsp - sp;
  568. X    }
  569. X    else
  570. X        lastretstr = retstr;
  571. X    while (tmps_max > tmps_base)    /* clean up after last eval */
  572. X        str_free(tmps_list[tmps_max--]);
  573. X    newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
  574. X    st = stack->ary_array;    /* possibly reallocated */
  575. X    retstr = st[newsp];
  576. X    if (newsp > sp)
  577. X        match = str_true(retstr);
  578. X    else
  579. X        match = FALSE;
  580. X    goto maybe;
  581. X
  582. X    /* if flipflop was true, flop it */
  583. X
  584. X    flipmaybe:
  585. X    if (match && cmdflags & CF_FLIP) {
  586. X        while (tmps_max > tmps_base)    /* clean up after last eval */
  587. X        str_free(tmps_list[tmps_max--]);
  588. X        if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  589. X        newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/
  590. X        cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  591. X        }
  592. X        else {
  593. X        newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */
  594. X        if (cmd->c_expr->arg_type == O_FLOP)    /* still toggled? */
  595. X            cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
  596. X        }
  597. X    }
  598. X    else if (cmdflags & CF_FLIP) {
  599. X        if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  600. X        match = TRUE;                /* force on */
  601. X        }
  602. X    }
  603. X
  604. X    /* at this point, match says whether our expression was true */
  605. X
  606. X    maybe:
  607. X    if (cmdflags & CF_INVERT)
  608. X        match = !match;
  609. X    if (!match)
  610. X        goto next_cmd;
  611. X    }
  612. X#ifdef TAINT
  613. X    tainted = 0;    /* modifier doesn't affect regular expression */
  614. X#endif
  615. X
  616. X    /* now to do the actual command, if any */
  617. X
  618. X    switch (cmd->c_type) {
  619. X    case C_NULL:
  620. X    fatal("panic: cmd_exec");
  621. X    case C_EXPR:            /* evaluated for side effects */
  622. X    if (cmd->ucmd.acmd.ac_expr) {    /* more to do? */
  623. X        if (gimme == G_ARRAY) {
  624. X        lastretstr = Nullstr;
  625. X        lastspbase = sp;
  626. X        lastsize = newsp - sp;
  627. X        }
  628. X        else
  629. X        lastretstr = retstr;
  630. X        while (tmps_max > tmps_base)    /* clean up after last eval */
  631. X        str_free(tmps_list[tmps_max--]);
  632. X        newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp);
  633. X        st = stack->ary_array;    /* possibly reallocated */
  634. X        retstr = st[newsp];
  635. X    }
  636. X    break;
  637. X    case C_NSWITCH:
  638. X    match = (int)str_gnum(STAB_STR(cmd->c_stab));
  639. X    goto doswitch;
  640. X    case C_CSWITCH:
  641. X    match = *(str_get(STAB_STR(cmd->c_stab))) & 255;
  642. X      doswitch:
  643. X    match -= cmd->ucmd.scmd.sc_offset;
  644. X    if (match < 0)
  645. X        match = 0;
  646. X    else if (match > cmd->ucmd.scmd.sc_max)
  647. X        match = cmd->c_slen;
  648. X    cmd = cmd->ucmd.scmd.sc_next[match];
  649. X    goto tail_recursion_entry;
  650. X    case C_NEXT:
  651. X    cmd = cmd->ucmd.ccmd.cc_alt;
  652. X    goto tail_recursion_entry;
  653. X    case C_ELSIF:
  654. X    fatal("panic: ELSIF");
  655. X    case C_IF:
  656. X    oldspat = curspat;
  657. X    oldsave = savestack->ary_fill;
  658. X#ifdef DEBUGGING
  659. X    olddlevel = dlevel;
  660. X#endif
  661. X    retstr = &str_yes;
  662. X    newsp = -2;
  663. X    if (cmd->ucmd.ccmd.cc_true) {
  664. X#ifdef DEBUGGING
  665. X        if (debug) {
  666. X        debname[dlevel] = 't';
  667. X        debdelim[dlevel] = '_';
  668. X        if (++dlevel >= dlmax)
  669. X            grow_dlevel();
  670. X        }
  671. X#endif
  672. X        newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
  673. X        st = stack->ary_array;    /* possibly reallocated */
  674. X        retstr = st[newsp];
  675. X    }
  676. X    curspat = oldspat;
  677. X    if (savestack->ary_fill > oldsave)
  678. X        restorelist(oldsave);
  679. X#ifdef DEBUGGING
  680. X    dlevel = olddlevel;
  681. X#endif
  682. X    cmd = cmd->ucmd.ccmd.cc_alt;
  683. X    goto tail_recursion_entry;
  684. X    case C_ELSE:
  685. X    oldspat = curspat;
  686. X    oldsave = savestack->ary_fill;
  687. X#ifdef DEBUGGING
  688. X    olddlevel = dlevel;
  689. X#endif
  690. X    retstr = &str_undef;
  691. X    newsp = -2;
  692. X    if (cmd->ucmd.ccmd.cc_true) {
  693. X#ifdef DEBUGGING
  694. X        if (debug) {
  695. X        debname[dlevel] = 'e';
  696. X        debdelim[dlevel] = '_';
  697. X        if (++dlevel >= dlmax)
  698. X            grow_dlevel();
  699. X        }
  700. X#endif
  701. X        newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
  702. X        st = stack->ary_array;    /* possibly reallocated */
  703. X        retstr = st[newsp];
  704. X    }
  705. X    curspat = oldspat;
  706. X    if (savestack->ary_fill > oldsave)
  707. X        restorelist(oldsave);
  708. X#ifdef DEBUGGING
  709. X    dlevel = olddlevel;
  710. X#endif
  711. X    break;
  712. X    case C_BLOCK:
  713. X    case C_WHILE:
  714. X    if (!(cmdflags & CF_ONCE)) {    /* first time through here? */
  715. X        cmdflags |= CF_ONCE;
  716. X        if (++loop_ptr >= loop_max) {
  717. X        loop_max += 128;
  718. X        Renew(loop_stack, loop_max, struct loop);
  719. X        }
  720. X        loop_stack[loop_ptr].loop_label = cmd->c_label;
  721. X        loop_stack[loop_ptr].loop_sp = sp;
  722. X#ifdef DEBUGGING
  723. X        if (debug & 4) {
  724. X        deb("(Pushing label #%d %s)\n",
  725. X          loop_ptr, cmd->c_label ? cmd->c_label : "");
  726. X        }
  727. X#endif
  728. X    }
  729. X    switch (setjmp(loop_stack[loop_ptr].loop_env)) {
  730. X    case O_LAST:
  731. X        /* retstr = lastretstr; */
  732. X        st = stack->ary_array;    /* possibly reallocated */
  733. X        if (lastretstr) {
  734. X        retstr = lastretstr;
  735. X        newsp = -2;
  736. X        }
  737. X        else {
  738. X        newsp = sp + lastsize;
  739. X        retstr = st[newsp];
  740. X        }
  741. X        curspat = oldspat;
  742. X        if (savestack->ary_fill > oldsave)
  743. X        restorelist(oldsave);
  744. X        goto next_cmd;
  745. X    case O_NEXT:
  746. X        goto next_iter;
  747. X    case O_REDO:
  748. X#ifdef DEBUGGING
  749. X        dlevel = olddlevel;
  750. X#endif
  751. X        goto doit;
  752. X    }
  753. X    oldspat = curspat;
  754. X    oldsave = savestack->ary_fill;
  755. X#ifdef DEBUGGING
  756. X    olddlevel = dlevel;
  757. X#endif
  758. X    doit:
  759. X    if (cmd->ucmd.ccmd.cc_true) {
  760. X#ifdef DEBUGGING
  761. X        if (debug) {
  762. X        debname[dlevel] = 't';
  763. X        debdelim[dlevel] = '_';
  764. X        if (++dlevel >= dlmax)
  765. X            grow_dlevel();
  766. X        }
  767. X#endif
  768. X        newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
  769. X        st = stack->ary_array;    /* possibly reallocated */
  770. X        retstr = st[newsp];
  771. X    }
  772. X    /* actually, this spot is rarely reached anymore since the above
  773. X     * cmd_exec() returns through longjmp().  Hooray for structure.
  774. X     */
  775. X      next_iter:
  776. X#ifdef DEBUGGING
  777. X    dlevel = olddlevel;
  778. X#endif
  779. X    if (cmd->ucmd.ccmd.cc_alt) {
  780. X#ifdef DEBUGGING
  781. X        if (debug) {
  782. X        debname[dlevel] = 'a';
  783. X        debdelim[dlevel] = '_';
  784. X        if (++dlevel >= dlmax)
  785. X            grow_dlevel();
  786. X        }
  787. X#endif
  788. X        newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme,sp);
  789. X        st = stack->ary_array;    /* possibly reallocated */
  790. X        retstr = st[newsp];
  791. X    }
  792. X      finish_while:
  793. X    curspat = oldspat;
  794. X    if (savestack->ary_fill > oldsave)
  795. X        restorelist(oldsave);
  796. X#ifdef DEBUGGING
  797. X    dlevel = olddlevel - 1;
  798. X#endif
  799. X    if (cmd->c_type != C_BLOCK)
  800. X        goto until_loop;    /* go back and evaluate conditional again */
  801. X    }
  802. X    if (cmdflags & CF_LOOP) {
  803. X    cmdflags |= CF_COND;        /* now test the condition */
  804. X#ifdef DEBUGGING
  805. X    dlevel = entdlevel;
  806. X#endif
  807. X    goto until_loop;
  808. X    }
  809. X  next_cmd:
  810. X    if (cmdflags & CF_ONCE) {
  811. X#ifdef DEBUGGING
  812. X    if (debug & 4) {
  813. X        tmps = loop_stack[loop_ptr].loop_label;
  814. X        deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : "");
  815. X    }
  816. X#endif
  817. X    loop_ptr--;
  818. X    if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY)
  819. X        restorelist(aryoptsave);
  820. X    }
  821. X    cmd = cmd->c_next;
  822. X    goto tail_recursion_entry;
  823. X}
  824. X
  825. X#ifdef DEBUGGING
  826. X#  ifndef VARARGS
  827. X/*VARARGS1*/
  828. Xdeb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
  829. Xchar *pat;
  830. X{
  831. X    register int i;
  832. X
  833. X    fprintf(stderr,"%-4ld",(long)line);
  834. X    for (i=0; i<dlevel; i++)
  835. X    fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
  836. X    fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
  837. X}
  838. X#  else
  839. X/*VARARGS1*/
  840. Xdeb(va_alist)
  841. Xva_dcl
  842. X{
  843. X    va_list args;
  844. X    char *pat;
  845. X    register int i;
  846. X
  847. X    va_start(args);
  848. X    fprintf(stderr,"%-4ld",(long)line);
  849. X    for (i=0; i<dlevel; i++)
  850. X    fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
  851. X
  852. X    pat = va_arg(args, char *);
  853. X    (void) vfprintf(stderr,pat,args);
  854. X    va_end( args );
  855. X}
  856. X#  endif
  857. X#endif
  858. X
  859. Xcopyopt(cmd,which)
  860. Xregister CMD *cmd;
  861. Xregister CMD *which;
  862. X{
  863. X    cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
  864. X    cmd->c_flags |= which->c_flags;
  865. X    cmd->c_short = which->c_short;
  866. X    cmd->c_slen = which->c_slen;
  867. X    cmd->c_stab = which->c_stab;
  868. X    return cmd->c_flags;
  869. X}
  870. X
  871. XARRAY *
  872. Xsaveary(stab)
  873. XSTAB *stab;
  874. X{
  875. X    register STR *str;
  876. X
  877. X    str = Str_new(10,0);
  878. X    str->str_state = SS_SARY;
  879. X    str->str_u.str_stab = stab;
  880. X    if (str->str_ptr) {
  881. X    Safefree(str->str_ptr);
  882. X    str->str_len = 0;
  883. X    }
  884. X    str->str_ptr = (char*)stab_array(stab);
  885. X    (void)apush(savestack,str); /* save array ptr */
  886. X    stab_xarray(stab) = Null(ARRAY*);
  887. X    return stab_xarray(aadd(stab));
  888. X}
  889. X
  890. XHASH *
  891. Xsavehash(stab)
  892. XSTAB *stab;
  893. X{
  894. X    register STR *str;
  895. X
  896. X    str = Str_new(11,0);
  897. X    str->str_state = SS_SHASH;
  898. X    str->str_u.str_stab = stab;
  899. X    if (str->str_ptr) {
  900. X    Safefree(str->str_ptr);
  901. X    str->str_len = 0;
  902. X    }
  903. X    str->str_ptr = (char*)stab_hash(stab);
  904. X    (void)apush(savestack,str); /* save hash ptr */
  905. X    stab_xhash(stab) = Null(HASH*);
  906. X    return stab_xhash(hadd(stab));
  907. X}
  908. X
  909. Xvoid
  910. Xsaveitem(item)
  911. Xregister STR *item;
  912. X{
  913. X    register STR *str;
  914. X
  915. X    (void)apush(savestack,item);        /* remember the pointer */
  916. X    str = Str_new(12,0);
  917. X    str_sset(str,item);
  918. X    (void)apush(savestack,str);            /* remember the value */
  919. X}
  920. X
  921. Xvoid
  922. Xsaveint(intp)
  923. Xint *intp;
  924. X{
  925. X    register STR *str;
  926. X
  927. X    str = Str_new(13,0);
  928. X    str->str_state = SS_SINT;
  929. X    str->str_u.str_useful = (long)*intp;    /* remember value */
  930. X    if (str->str_ptr) {
  931. X    Safefree(str->str_ptr);
  932. X    str->str_len = 0;
  933. X    }
  934. X    str->str_ptr = (char*)intp;        /* remember pointer */
  935. X    (void)apush(savestack,str);
  936. X}
  937. X
  938. Xvoid
  939. Xsavelong(longp)
  940. Xlong *longp;
  941. X{
  942. X    register STR *str;
  943. X
  944. X    str = Str_new(14,0);
  945. X    str->str_state = SS_SLONG;
  946. X    str->str_u.str_useful = *longp;        /* remember value */
  947. X    if (str->str_ptr) {
  948. X    Safefree(str->str_ptr);
  949. X    str->str_len = 0;
  950. X    }
  951. X    str->str_ptr = (char*)longp;        /* remember pointer */
  952. X    (void)apush(savestack,str);
  953. X}
  954. X
  955. Xvoid
  956. Xsavesptr(sptr)
  957. XSTR **sptr;
  958. X{
  959. X    register STR *str;
  960. X
  961. X    str = Str_new(15,0);
  962. X    str->str_state = SS_SSTRP;
  963. X    str->str_magic = *sptr;        /* remember value */
  964. X    if (str->str_ptr) {
  965. X    Safefree(str->str_ptr);
  966. X    str->str_len = 0;
  967. X    }
  968. X    str->str_ptr = (char*)sptr;        /* remember pointer */
  969. X    (void)apush(savestack,str);
  970. X}
  971. X
  972. Xvoid
  973. Xsavenostab(stab)
  974. XSTAB *stab;
  975. X{
  976. X    register STR *str;
  977. X
  978. X    str = Str_new(16,0);
  979. X    str->str_state = SS_SNSTAB;
  980. X    str->str_magic = (STR*)stab;    /* remember which stab to free */
  981. X    (void)apush(savestack,str);
  982. X}
  983. X
  984. Xvoid
  985. Xsavehptr(hptr)
  986. XHASH **hptr;
  987. X{
  988. X    register STR *str;
  989. X
  990. X    str = Str_new(17,0);
  991. X    str->str_state = SS_SHPTR;
  992. X    str->str_u.str_hash = *hptr;    /* remember value */
  993. X    if (str->str_ptr) {
  994. X    Safefree(str->str_ptr);
  995. X    str->str_len = 0;
  996. X    }
  997. X    str->str_ptr = (char*)hptr;        /* remember pointer */
  998. X    (void)apush(savestack,str);
  999. X}
  1000. X
  1001. Xvoid
  1002. Xsavelist(sarg,maxsarg)
  1003. Xregister STR **sarg;
  1004. Xint maxsarg;
  1005. X{
  1006. X    register STR *str;
  1007. X    register int i;
  1008. X
  1009. X    for (i = 1; i <= maxsarg; i++) {
  1010. X    (void)apush(savestack,sarg[i]);        /* remember the pointer */
  1011. X    str = Str_new(18,0);
  1012. X    str_sset(str,sarg[i]);
  1013. X    (void)apush(savestack,str);            /* remember the value */
  1014. X    }
  1015. X}
  1016. X
  1017. Xvoid
  1018. Xrestorelist(base)
  1019. Xint base;
  1020. X{
  1021. X    register STR *str;
  1022. X    register STR *value;
  1023. X    register STAB *stab;
  1024. X
  1025. X    if (base < -1)
  1026. X    fatal("panic: corrupt saved stack index");
  1027. X    while (savestack->ary_fill > base) {
  1028. X    value = apop(savestack);
  1029. X    switch (value->str_state) {
  1030. X    case SS_NORM:                /* normal string */
  1031. X    case SS_INCR:
  1032. X        str = apop(savestack);
  1033. X        str_replace(str,value);
  1034. X        STABSET(str);
  1035. X        break;
  1036. X    case SS_SARY:                /* array reference */
  1037. X        stab = value->str_u.str_stab;
  1038. X        afree(stab_xarray(stab));
  1039. X        stab_xarray(stab) = (ARRAY*)value->str_ptr;
  1040. X        value->str_ptr = Nullch;
  1041. X        str_free(value);
  1042. X        break;
  1043. X    case SS_SHASH:                /* hash reference */
  1044. X        stab = value->str_u.str_stab;
  1045. X        (void)hfree(stab_xhash(stab));
  1046. X        stab_xhash(stab) = (HASH*)value->str_ptr;
  1047. X        value->str_ptr = Nullch;
  1048. X        str_free(value);
  1049. X        break;
  1050. X    case SS_SINT:                /* int reference */
  1051. X        *((int*)value->str_ptr) = (int)value->str_u.str_useful;
  1052. X        value->str_ptr = Nullch;
  1053. X        str_free(value);
  1054. X        break;
  1055. X    case SS_SLONG:                /* long reference */
  1056. X        *((long*)value->str_ptr) = value->str_u.str_useful;
  1057. X        value->str_ptr = Nullch;
  1058. X        str_free(value);
  1059. X        break;
  1060. X    case SS_SSTRP:                /* STR* reference */
  1061. X        *((STR**)value->str_ptr) = value->str_magic;
  1062. X        value->str_magic = Nullstr;
  1063. X        value->str_ptr = Nullch;
  1064. X        str_free(value);
  1065. X        break;
  1066. X    case SS_SHPTR:                /* HASH* reference */
  1067. X        *((HASH**)value->str_ptr) = value->str_u.str_hash;
  1068. X        value->str_ptr = Nullch;
  1069. X        str_free(value);
  1070. X        break;
  1071. X    case SS_SNSTAB:
  1072. X        stab = (STAB*)value->str_magic;
  1073. X        value->str_magic = Nullstr;
  1074. X        (void)stab_clear(stab);
  1075. X        str_free(value);
  1076. X        break;
  1077. X    default:
  1078. X        fatal("panic: restorelist inconsistency");
  1079. X    }
  1080. X    }
  1081. X}
  1082. X
  1083. Xvoid
  1084. Xgrow_dlevel()
  1085. X{
  1086. X    dlmax += 128;
  1087. X    Renew(debname, dlmax, char);
  1088. X    Renew(debdelim, dlmax, char);
  1089. X}
  1090. !STUFFY!FUNK!
  1091. echo Extracting config.H
  1092. sed >config.H <<'!STUFFY!FUNK!' -e 's/X//'
  1093. X/* config.h
  1094. X * This file was produced by running the config.h.SH script, which
  1095. X * gets its values from config.sh, which is generally produced by
  1096. X * running Configure.
  1097. X *
  1098. X * Feel free to modify any of this as the need arises.  Note, however,
  1099. X * that running config.h.SH again will wipe out any changes you've made.
  1100. X * For a more permanent change edit config.sh and rerun config.h.SH.
  1101. X */
  1102. X
  1103. X
  1104. X/* EUNICE:
  1105. X *    This symbol, if defined, indicates that the program is being compiled
  1106. X *    under the EUNICE package under VMS.  The program will need to handle
  1107. X *    things like files that don't go away the first time you unlink them,
  1108. X *    due to version numbering.  It will also need to compensate for lack
  1109. X *    of a respectable link() command.
  1110. X */
  1111. X/* VMS:
  1112. X *    This symbol, if defined, indicates that the program is running under
  1113. X *    VMS.  It is currently only set in conjunction with the EUNICE symbol.
  1114. X */
  1115. X/*#undef    EUNICE        /**/
  1116. X/*#undef    VMS        /**/
  1117. X
  1118. X/* BIN:
  1119. X *    This symbol holds the name of the directory in which the user wants
  1120. X *    to put publicly executable images for the package in question.  It
  1121. X *    is most often a local directory such as /usr/local/bin.
  1122. X */
  1123. X#define BIN "/usr/local/bin"             /**/
  1124. X
  1125. X/* BYTEORDER:
  1126. X *    This symbol contains an encoding of the order of bytes in a long.
  1127. X *    Usual values (in octal) are 01234, 04321, 02143, 03412...
  1128. X */
  1129. X#define BYTEORDER 01234        /**/
  1130. X
  1131. X/* CPPSTDIN:
  1132. X *    This symbol contains the first part of the string which will invoke
  1133. X *    the C preprocessor on the standard input and produce to standard
  1134. X *    output.     Typical value of "cc -E" or "/lib/cpp".
  1135. X */
  1136. X/* CPPMINUS:
  1137. X *    This symbol contains the second part of the string which will invoke
  1138. X *    the C preprocessor on the standard input and produce to standard
  1139. X *    output.  This symbol will have the value "-" if CPPSTDIN needs a minus
  1140. X *    to specify standard input, otherwise the value is "".
  1141. X */
  1142. X#define CPPSTDIN "/lib/cpp"
  1143. X#define CPPMINUS ""
  1144. X
  1145. X/* BCMP:
  1146. X *    This symbol, if defined, indicates that the bcmp routine is available
  1147. X *    to compare blocks of memory.  If undefined, use memcmp.  If that's
  1148. X *    not available, roll your own.
  1149. X */
  1150. X#define    BCMP        /**/
  1151. X
  1152. X/* BCOPY:
  1153. X *    This symbol, if defined, indicates that the bcopy routine is available
  1154. X *    to copy blocks of memory.  Otherwise you should probably use memcpy().
  1155. X */
  1156. X#define    BCOPY        /**/
  1157. X
  1158. X/* CHARSPRINTF:
  1159. X *    This symbol is defined if this system declares "char *sprintf()" in
  1160. X *    stdio.h.  The trend seems to be to declare it as "int sprintf()".  It
  1161. X *    is up to the package author to declare sprintf correctly based on the
  1162. X *    symbol.
  1163. X */
  1164. X#define    CHARSPRINTF     /**/
  1165. X
  1166. X/* CRYPT:
  1167. X *    This symbol, if defined, indicates that the crypt routine is available
  1168. X *    to encrypt passwords and the like.
  1169. X */
  1170. X#define    CRYPT        /**/
  1171. X
  1172. X/* DOSUID:
  1173. X *    This symbol, if defined, indicates that the C program should
  1174. X *    check the script that it is executing for setuid/setgid bits, and
  1175. X *    attempt to emulate setuid/setgid on systems that have disabled
  1176. X *    setuid #! scripts because the kernel can't do it securely.
  1177. X *    It is up to the package designer to make sure that this emulation
  1178. X *    is done securely.  Among other things, it should do an fstat on
  1179. X *    the script it just opened to make sure it really is a setuid/setgid
  1180. X *    script, it should make sure the arguments passed correspond exactly
  1181. X *    to the argument on the #! line, and it should not trust any
  1182. X *    subprocesses to which it must pass the filename rather than the
  1183. X *    file descriptor of the script to be executed.
  1184. X */
  1185. X#define DOSUID        /**/
  1186. X
  1187. X/* DUP2:
  1188. X *    This symbol, if defined, indicates that the dup2 routine is available
  1189. X *    to dup file descriptors.  Otherwise you should use dup().
  1190. X */
  1191. X#define    DUP2        /**/
  1192. X
  1193. X/* FCHMOD:
  1194. X *    This symbol, if defined, indicates that the fchmod routine is available
  1195. X *    to change mode of opened files.  If unavailable, use chmod().
  1196. X */
  1197. X#define    FCHMOD        /**/
  1198. X
  1199. X/* FCHOWN:
  1200. X *    This symbol, if defined, indicates that the fchown routine is available
  1201. X *    to change ownership of opened files.  If unavailable, use chown().
  1202. X */
  1203. X#define    FCHOWN        /**/
  1204. X
  1205. X/* FCNTL:
  1206. X *    This symbol, if defined, indicates to the C program that it should
  1207. X *    include fcntl.h.
  1208. X */
  1209. X#define    FCNTL        /**/
  1210. X
  1211. X/* FLOCK:
  1212. X *    This symbol, if defined, indicates that the flock() routine is
  1213. X *    available to do file locking.
  1214. X */
  1215. X#define    FLOCK        /**/
  1216. X
  1217. X/* GETGROUPS:
  1218. X *    This symbol, if defined, indicates that the getgroups() routine is
  1219. X *    available to get the list of process groups.  If unavailable, multiple
  1220. X *    groups are probably not supported.
  1221. X */
  1222. X#define    GETGROUPS        /**/
  1223. X
  1224. X/* GETHOSTENT:
  1225. X *    This symbol, if defined, indicates that the gethostent() routine is
  1226. X *    available to lookup host names in some data base or other.
  1227. X */
  1228. X#define    GETHOSTENT        /**/
  1229. X
  1230. X/* GETPGRP:
  1231. X *    This symbol, if defined, indicates that the getpgrp() routine is
  1232. X *    available to get the current process group.
  1233. X */
  1234. X#define    GETPGRP        /**/
  1235. X
  1236. X/* GETPRIORITY:
  1237. X *    This symbol, if defined, indicates that the getpriority() routine is
  1238. X *    available to get a process's priority.
  1239. X */
  1240. X#define    GETPRIORITY        /**/
  1241. X
  1242. X/* HTONS:
  1243. X *    This symbol, if defined, indicates that the htons routine (and friends)
  1244. X *    are available to do network order byte swapping.
  1245. X */
  1246. X/* HTONL:
  1247. X *    This symbol, if defined, indicates that the htonl routine (and friends)
  1248. X *    are available to do network order byte swapping.
  1249. X */
  1250. X/* NTOHS:
  1251. X *    This symbol, if defined, indicates that the ntohs routine (and friends)
  1252. X *    are available to do network order byte swapping.
  1253. X */
  1254. X/* NTOHL:
  1255. X *    This symbol, if defined, indicates that the ntohl routine (and friends)
  1256. X *    are available to do network order byte swapping.
  1257. X */
  1258. X#define    HTONS        /**/
  1259. X#define    HTONL        /**/
  1260. X#define    NTOHS        /**/
  1261. X#define    NTOHL        /**/
  1262. X
  1263. X/* index:
  1264. X *    This preprocessor symbol is defined, along with rindex, if the system
  1265. X *    uses the strchr and strrchr routines instead.
  1266. X */
  1267. X/* rindex:
  1268. X *    This preprocessor symbol is defined, along with index, if the system
  1269. X *    uses the strchr and strrchr routines instead.
  1270. X */
  1271. X/*#undef    index strchr    /* cultural */
  1272. X/*#undef    rindex strrchr    /*  differences? */
  1273. X
  1274. X/* IOCTL:
  1275. X *    This symbol, if defined, indicates that sys/ioctl.h exists and should
  1276. X *    be included.
  1277. X */
  1278. X#define    IOCTL        /**/
  1279. X
  1280. X/* KILLPG:
  1281. X *    This symbol, if defined, indicates that the killpg routine is available
  1282. X *    to kill process groups.  If unavailable, you probably should use kill
  1283. X *    with a negative process number.
  1284. X */
  1285. X#define    KILLPG        /**/
  1286. X
  1287. X/* MEMCMP:
  1288. X *    This symbol, if defined, indicates that the memcmp routine is available
  1289. X *    to compare blocks of memory.  If undefined, roll your own.
  1290. X */
  1291. X#define    MEMCMP        /**/
  1292. X
  1293. X/* MEMCPY:
  1294. X *    This symbol, if defined, indicates that the memcpy routine is available
  1295. X *    to copy blocks of memory.  Otherwise you should probably use bcopy().
  1296. X *    If neither is defined, roll your own.
  1297. X */
  1298. X#define    MEMCPY        /**/
  1299. X
  1300. X/* MKDIR:
  1301. X *    This symbol, if defined, indicates that the mkdir routine is available
  1302. X *    to create directories.  Otherwise you should fork off a new process to
  1303. X *    exec /bin/mkdir.
  1304. X */
  1305. X#define    MKDIR        /**/
  1306. X
  1307. X/* NDBM:
  1308. X *    This symbol, if defined, indicates that ndbm.h exists and should
  1309. X *    be included.
  1310. X */
  1311. X#define    NDBM        /**/
  1312. X
  1313. X/* ODBM:
  1314. X *    This symbol, if defined, indicates that dbm.h exists and should
  1315. X *    be included.
  1316. X */
  1317. X#define    ODBM        /**/
  1318. X
  1319. X/* READDIR:
  1320. X *    This symbol, if defined, indicates that the readdir routine is available
  1321. X *    from the C library to create directories.
  1322. X */
  1323. X#define    READDIR        /**/
  1324. X
  1325. X/* RENAME:
  1326. X *    This symbol, if defined, indicates that the rename routine is available
  1327. X *    to rename files.  Otherwise you should do the unlink(), link(), unlink()
  1328. X *    trick.
  1329. X */
  1330. X#define    RENAME        /**/
  1331. X
  1332. X/* RMDIR:
  1333. X *    This symbol, if defined, indicates that the rmdir routine is available
  1334. X *    to remove directories.  Otherwise you should fork off a new process to
  1335. X *    exec /bin/rmdir.
  1336. X */
  1337. X#define    RMDIR        /**/
  1338. X
  1339. X/* SETEGID:
  1340. X *    This symbol, if defined, indicates that the setegid routine is available
  1341. X *    to change the effective gid of the current program.
  1342. X */
  1343. X#define    SETEGID        /**/
  1344. X
  1345. X/* SETEUID:
  1346. X *    This symbol, if defined, indicates that the seteuid routine is available
  1347. X *    to change the effective uid of the current program.
  1348. X */
  1349. X#define    SETEUID        /**/
  1350. X
  1351. X/* SETPGRP:
  1352. X *    This symbol, if defined, indicates that the setpgrp() routine is
  1353. X *    available to set the current process group.
  1354. X */
  1355. X#define    SETPGRP        /**/
  1356. X
  1357. X/* SETPRIORITY:
  1358. X *    This symbol, if defined, indicates that the setpriority() routine is
  1359. X *    available to set a process's priority.
  1360. X */
  1361. X#define    SETPRIORITY        /**/
  1362. X
  1363. X/* SETREGID:
  1364. X *    This symbol, if defined, indicates that the setregid routine is available
  1365. X *    to change the real and effective gid of the current program.
  1366. X */
  1367. X#define    SETREGID        /**/
  1368. X
  1369. X/* SETREUID:
  1370. X *    This symbol, if defined, indicates that the setreuid routine is available
  1371. X *    to change the real and effective uid of the current program.
  1372. X */
  1373. X#define    SETREUID        /**/
  1374. X
  1375. X/* SETRGID:
  1376. X *    This symbol, if defined, indicates that the setrgid routine is available
  1377. X *    to change the real gid of the current program.
  1378. X */
  1379. X#define    SETRGID        /**/
  1380. X
  1381. X/* SETRUID:
  1382. X *    This symbol, if defined, indicates that the setruid routine is available
  1383. X *    to change the real uid of the current program.
  1384. X */
  1385. X#define    SETRUID        /**/
  1386. X
  1387. X/* SOCKET:
  1388. X *    This symbol, if defined, indicates that the BSD socket interface is
  1389. X *    supported.
  1390. X */
  1391. X/* SOCKETPAIR:
  1392. X *    This symbol, if defined, indicates that the BSD socketpair call is
  1393. X *    supported.
  1394. X */
  1395. X/* OLDSOCKET:
  1396. X *    This symbol, if defined, indicates that the 4.1c BSD socket interface
  1397. X *    is supported instead of the 4.2/4.3 BSD socket interface.
  1398. X */
  1399. X#define    SOCKET        /**/
  1400. X
  1401. X#define    SOCKETPAIR    /**/
  1402. X
  1403. X/*#undef    OLDSOCKET    /**/
  1404. X
  1405. X/* STATBLOCKS:
  1406. X *    This symbol is defined if this system has a stat structure declaring
  1407. X *    st_blksize and st_blocks.
  1408. X */
  1409. X#define    STATBLOCKS     /**/
  1410. X
  1411. X/* STDSTDIO:
  1412. X *    This symbol is defined if this system has a FILE structure declaring
  1413. X *    _ptr and _cnt in stdio.h.
  1414. X */
  1415. X#define    STDSTDIO     /**/
  1416. X
  1417. X/* STRUCTCOPY:
  1418. X *    This symbol, if defined, indicates that this C compiler knows how
  1419. X *    to copy structures.  If undefined, you'll need to use a block copy
  1420. X *    routine of some sort instead.
  1421. X */
  1422. X#define    STRUCTCOPY    /**/
  1423. X
  1424. X/* SYMLINK:
  1425. X *    This symbol, if defined, indicates that the symlink routine is available
  1426. X *    to create symbolic links.
  1427. X */
  1428. X#define    SYMLINK        /**/
  1429. X
  1430. X/* SYSCALL:
  1431. X *    This symbol, if defined, indicates that the syscall routine is available
  1432. X *    to call arbitrary system calls.  If undefined, that's tough.
  1433. X */
  1434. X#define    SYSCALL        /**/
  1435. X
  1436. X/* TMINSYS:
  1437. X *    This symbol is defined if this system declares "struct tm" in
  1438. X *    in <sys/time.h> rather than <time.h>.  We can't just say
  1439. X *    -I/usr/include/sys because some systems have both time files, and
  1440. X *    the -I trick gets the wrong one.
  1441. X */
  1442. X/* I_SYSTIME:
  1443. X *    This symbol is defined if this system has the file <sys/time.h>.
  1444. X */
  1445. X/*#undef    TMINSYS     /**/
  1446. X#define    I_SYSTIME     /**/
  1447. X
  1448. X/* VARARGS:
  1449. X *    This symbol, if defined, indicates to the C program that it should
  1450. X *    include varargs.h.
  1451. X */
  1452. X#define    VARARGS        /**/
  1453. X
  1454. X/* vfork:
  1455. X *    This symbol, if defined, remaps the vfork routine to fork if the
  1456. X *    vfork() routine isn't supported here.
  1457. X */
  1458. X/*#undef    vfork fork    /**/
  1459. X
  1460. X/* VOIDSIG:
  1461. X *    This symbol is defined if this system declares "void (*signal())()" in
  1462. X *    signal.h.  The old way was to declare it as "int (*signal())()".  It
  1463. X *    is up to the package author to declare things correctly based on the
  1464. X *    symbol.
  1465. X */
  1466. X/*#undef    VOIDSIG     /**/
  1467. X
  1468. X/* VPRINTF:
  1469. X *    This symbol, if defined, indicates that the vprintf routine is available
  1470. X *    to printf with a pointer to an argument list.  If unavailable, you
  1471. X *    may need to write your own, probably in terms of _doprnt().
  1472. X */
  1473. X/* CHARVSPRINTF:
  1474. X *    This symbol is defined if this system has vsprintf() returning type
  1475. X *    (char*).  The trend seems to be to declare it as "int vsprintf()".  It
  1476. X *    is up to the package author to declare vsprintf correctly based on the
  1477. X *    symbol.
  1478. X */
  1479. X/*#undef    VPRINTF        /**/
  1480. X/*#undef    CHARVSPRINTF     /**/
  1481. X
  1482. X/* GIDTYPE:
  1483. X *    This symbol has a value like gid_t, int, ushort, or whatever type is
  1484. X *    used to declare group ids in the kernel.
  1485. X */
  1486. X#define GIDTYPE gid_t        /**/
  1487. X
  1488. X/* I_DIRENT:
  1489. X *    This symbol, if defined, indicates to the C program that it should
  1490. X *    include dirent.h.
  1491. X */
  1492. X/* DIRNAMLEN:
  1493. X *    This symbol, if defined, indicates to the C program that the length
  1494. X *    of directory entry names is provided by a d_namlen field.  Otherwise
  1495. X *    you need to do strlen() on the d_name field.
  1496. X */
  1497. X/*#undef    I_DIRENT        /**/
  1498. X#define    DIRNAMLEN        /**/
  1499. X
  1500. X/* I_FCNTL:
  1501. X *    This symbol, if defined, indicates to the C program that it should
  1502. X *    include fcntl.h.
  1503. X */
  1504. X#define    I_FCNTL        /**/
  1505. X
  1506. X/* I_GRP:
  1507. X *    This symbol, if defined, indicates to the C program that it should
  1508. X *    include grp.h.
  1509. X */
  1510. X#define    I_GRP        /**/
  1511. X
  1512. X/* I_PWD:
  1513. X *    This symbol, if defined, indicates to the C program that it should
  1514. X *    include pwd.h.
  1515. X */
  1516. X/* PWQUOTA:
  1517. X *    This symbol, if defined, indicates to the C program that struct passwd
  1518. X *    contains pw_quota.
  1519. X */
  1520. X/* PWAGE:
  1521. X *    This symbol, if defined, indicates to the C program that struct passwd
  1522. X *    contains pw_age.
  1523. X */
  1524. X#define    I_PWD        /**/
  1525. X#define    PWQUOTA        /**/
  1526. X/*#undef    PWAGE        /**/
  1527. X
  1528. X/* I_SYSDIR:
  1529. X *    This symbol, if defined, indicates to the C program that it should
  1530. X *    include sys/dir.h.
  1531. X */
  1532. X#define    I_SYSDIR        /**/
  1533. X
  1534. X/* I_SYSIOCTL:
  1535. X *    This symbol, if defined, indicates that sys/ioctl.h exists and should
  1536. X *    be included.
  1537. X */
  1538. X#define    I_SYSIOCTL        /**/
  1539. X
  1540. X/* I_VARARGS:
  1541. X *    This symbol, if defined, indicates to the C program that it should
  1542. X *    include varargs.h.
  1543. X */
  1544. X#define    I_VARARGS        /**/
  1545. X
  1546. X/* INTSIZE:
  1547. X *    This symbol contains the size of an int, so that the C preprocessor
  1548. X *    can make decisions based on it.
  1549. X */
  1550. X#define INTSIZE 4        /**/
  1551. X
  1552. X/* RANDBITS:
  1553. X *    This symbol contains the number of bits of random number the rand()
  1554. X *    function produces.  Usual values are 15, 16, and 31.
  1555. X */
  1556. X#define RANDBITS 31        /**/
  1557. X
  1558. X/* SIG_NAME:
  1559. X *    This symbol contains an list of signal names in order.
  1560. X */
  1561. X#define SIG_NAME "ZERO","HUP","INT","QUIT","ILL","TRAP","IOT","EMT","FPE","KILL","BUS","SEGV","SYS","PIPE","ALRM","TERM","URG","STOP","TSTP","CONT","CHLD","TTIN","TTOU","IO","XCPU","XFSZ","VTALRM","PROF","WINCH","USR1","USR2"        /**/
  1562. X
  1563. X/* STDCHAR:
  1564. X *    This symbol is defined to be the type of char used in stdio.h.
  1565. X *    It has the values "unsigned char" or "char".
  1566. X */
  1567. X#define STDCHAR char    /**/
  1568. X
  1569. X/* UIDTYPE:
  1570. X *    This symbol has a value like uid_t, int, ushort, or whatever type is
  1571. X *    used to declare user ids in the kernel.
  1572. X */
  1573. X#define UIDTYPE uid_t        /**/
  1574. X
  1575. X/* VOIDFLAGS:
  1576. X *    This symbol indicates how much support of the void type is given by this
  1577. X *    compiler.  What various bits mean:
  1578. X *
  1579. X *        1 = supports declaration of void
  1580. X *        2 = supports arrays of pointers to functions returning void
  1581. X *        4 = supports comparisons between pointers to void functions and
  1582. X *            addresses of void functions
  1583. X *
  1584. X *    The package designer should define VOIDUSED to indicate the requirements
  1585. X *    of the package.  This can be done either by #defining VOIDUSED before
  1586. X *    including config.h, or by defining defvoidused in Myinit.U.  If the
  1587. X *    latter approach is taken, only those flags will be tested.  If the
  1588. X *    level of void support necessary is not present, defines void to int.
  1589. X */
  1590. X#ifndef VOIDUSED
  1591. X#define VOIDUSED 7
  1592. X#endif
  1593. X#define VOIDFLAGS 7
  1594. X#if (VOIDFLAGS & VOIDUSED) != VOIDUSED
  1595. X#define void int        /* is void to be avoided? */
  1596. X#define M_VOID        /* Xenix strikes again */
  1597. X#endif
  1598. X
  1599. X/* PRIVLIB:
  1600. X *    This symbol contains the name of the private library for this package.
  1601. X *    The library is private in the sense that it needn't be in anyone's
  1602. X *    execution path, but it should be accessible by the world.  The program
  1603. X *    should be prepared to do ~ expansion.
  1604. X */
  1605. X#define PRIVLIB "/usr/local/lib/perl"        /**/
  1606. X
  1607. !STUFFY!FUNK!
  1608. echo Extracting x2p/util.c
  1609. sed >x2p/util.c <<'!STUFFY!FUNK!' -e 's/X//'
  1610. X/* $Header: util.c,v 3.0 89/10/18 15:35:35 lwall Locked $
  1611. X *
  1612. X *    Copyright (c) 1989, Larry Wall
  1613. X *
  1614. X *    You may distribute under the terms of the GNU General Public License
  1615. X *    as specified in the README file that comes with the perl 3.0 kit.
  1616. X *
  1617. X * $Log:    util.c,v $
  1618. X * Revision 3.0  89/10/18  15:35:35  lwall
  1619. X * 3.0 baseline
  1620. X * 
  1621. X */
  1622. X
  1623. X#include <stdio.h>
  1624. X
  1625. X#include "handy.h"
  1626. X#include "EXTERN.h"
  1627. X#include "a2p.h"
  1628. X#include "INTERN.h"
  1629. X#include "util.h"
  1630. X
  1631. X#define FLUSH
  1632. X#define MEM_SIZE unsigned int
  1633. X
  1634. Xstatic char nomem[] = "Out of memory!\n";
  1635. X
  1636. X/* paranoid version of malloc */
  1637. X
  1638. Xstatic int an = 0;
  1639. X
  1640. Xchar *
  1641. Xsafemalloc(size)
  1642. XMEM_SIZE size;
  1643. X{
  1644. X    char *ptr;
  1645. X    char *malloc();
  1646. X
  1647. X    ptr = malloc(size?size:1);    /* malloc(0) is NASTY on our system */
  1648. X#ifdef DEBUGGING
  1649. X    if (debug & 128)
  1650. X    fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
  1651. X#endif
  1652. X    if (ptr != Nullch)
  1653. X    return ptr;
  1654. X    else {
  1655. X    fputs(nomem,stdout) FLUSH;
  1656. X    exit(1);
  1657. X    }
  1658. X    /*NOTREACHED*/
  1659. X}
  1660. X
  1661. X/* paranoid version of realloc */
  1662. X
  1663. Xchar *
  1664. Xsaferealloc(where,size)
  1665. Xchar *where;
  1666. XMEM_SIZE size;
  1667. X{
  1668. X    char *ptr;
  1669. X    char *realloc();
  1670. X
  1671. X    ptr = realloc(where,size?size:1);    /* realloc(0) is NASTY on our system */
  1672. X#ifdef DEBUGGING
  1673. X    if (debug & 128) {
  1674. X    fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
  1675. X    fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
  1676. X    }
  1677. X#endif
  1678. X    if (ptr != Nullch)
  1679. X    return ptr;
  1680. X    else {
  1681. X    fputs(nomem,stdout) FLUSH;
  1682. X    exit(1);
  1683. X    }
  1684. X    /*NOTREACHED*/
  1685. X}
  1686. X
  1687. X/* safe version of free */
  1688. X
  1689. Xsafefree(where)
  1690. Xchar *where;
  1691. X{
  1692. X#ifdef DEBUGGING
  1693. X    if (debug & 128)
  1694. X    fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
  1695. X#endif
  1696. X    free(where);
  1697. X}
  1698. X
  1699. X/* safe version of string copy */
  1700. X
  1701. Xchar *
  1702. Xsafecpy(to,from,len)
  1703. Xchar *to;
  1704. Xregister char *from;
  1705. Xregister int len;
  1706. X{
  1707. X    register char *dest = to;
  1708. X
  1709. X    if (from != Nullch) 
  1710. X    for (len--; len && (*dest++ = *from++); len--) ;
  1711. X    *dest = '\0';
  1712. X    return to;
  1713. X}
  1714. X
  1715. X#ifdef undef
  1716. X/* safe version of string concatenate, with \n deletion and space padding */
  1717. X
  1718. Xchar *
  1719. Xsafecat(to,from,len)
  1720. Xchar *to;
  1721. Xregister char *from;
  1722. Xregister int len;
  1723. X{
  1724. X    register char *dest = to;
  1725. X
  1726. X    len--;                /* leave room for null */
  1727. X    if (*dest) {
  1728. X    while (len && *dest++) len--;
  1729. X    if (len) {
  1730. X        len--;
  1731. X        *(dest-1) = ' ';
  1732. X    }
  1733. X    }
  1734. X    if (from != Nullch)
  1735. X    while (len && (*dest++ = *from++)) len--;
  1736. X    if (len)
  1737. X    dest--;
  1738. X    if (*(dest-1) == '\n')
  1739. X    dest--;
  1740. X    *dest = '\0';
  1741. X    return to;
  1742. X}
  1743. X#endif
  1744. X
  1745. X/* copy a string up to some (non-backslashed) delimiter, if any */
  1746. X
  1747. Xchar *
  1748. Xcpytill(to,from,delim)
  1749. Xregister char *to, *from;
  1750. Xregister int delim;
  1751. X{
  1752. X    for (; *from; from++,to++) {
  1753. X    if (*from == '\\') {
  1754. X        if (from[1] == delim)
  1755. X        from++;
  1756. X        else if (from[1] == '\\')
  1757. X        *to++ = *from++;
  1758. X    }
  1759. X    else if (*from == delim)
  1760. X        break;
  1761. X    *to = *from;
  1762. X    }
  1763. X    *to = '\0';
  1764. X    return from;
  1765. X}
  1766. X
  1767. X
  1768. Xchar *
  1769. Xcpy2(to,from,delim)
  1770. Xregister char *to, *from;
  1771. Xregister int delim;
  1772. X{
  1773. X    for (; *from; from++,to++) {
  1774. X    if (*from == '\\')
  1775. X        *to++ = *from++;
  1776. X    else if (*from == '$')
  1777. X        *to++ = '\\';
  1778. X    else if (*from == delim)
  1779. X        break;
  1780. X    *to = *from;
  1781. X    }
  1782. X    *to = '\0';
  1783. X    return from;
  1784. X}
  1785. X
  1786. X/* return ptr to little string in big string, NULL if not found */
  1787. X
  1788. Xchar *
  1789. Xinstr(big, little)
  1790. Xchar *big, *little;
  1791. X
  1792. X{
  1793. X    register char *t, *s, *x;
  1794. X
  1795. X    for (t = big; *t; t++) {
  1796. X    for (x=t,s=little; *s; x++,s++) {
  1797. X        if (!*x)
  1798. X        return Nullch;
  1799. X        if (*s != *x)
  1800. X        break;
  1801. X    }
  1802. X    if (!*s)
  1803. X        return t;
  1804. X    }
  1805. X    return Nullch;
  1806. X}
  1807. X
  1808. X/* copy a string to a safe spot */
  1809. X
  1810. Xchar *
  1811. Xsavestr(str)
  1812. Xchar *str;
  1813. X{
  1814. X    register char *newaddr = safemalloc((MEM_SIZE)(strlen(str)+1));
  1815. X
  1816. X    (void)strcpy(newaddr,str);
  1817. X    return newaddr;
  1818. X}
  1819. X
  1820. X/* grow a static string to at least a certain length */
  1821. X
  1822. Xvoid
  1823. Xgrowstr(strptr,curlen,newlen)
  1824. Xchar **strptr;
  1825. Xint *curlen;
  1826. Xint newlen;
  1827. X{
  1828. X    if (newlen > *curlen) {        /* need more room? */
  1829. X    if (*curlen)
  1830. X        *strptr = saferealloc(*strptr,(MEM_SIZE)newlen);
  1831. X    else
  1832. X        *strptr = safemalloc((MEM_SIZE)newlen);
  1833. X    *curlen = newlen;
  1834. X    }
  1835. X}
  1836. X
  1837. X/*VARARGS1*/
  1838. Xfatal(pat,a1,a2,a3,a4)
  1839. Xchar *pat;
  1840. X{
  1841. X    fprintf(stderr,pat,a1,a2,a3,a4);
  1842. X    exit(1);
  1843. X}
  1844. X
  1845. X/*VARARGS1*/
  1846. Xwarn(pat,a1,a2,a3,a4)
  1847. Xchar *pat;
  1848. X{
  1849. X    fprintf(stderr,pat,a1,a2,a3,a4);
  1850. X}
  1851. X
  1852. Xstatic bool firstsetenv = TRUE;
  1853. Xextern char **environ;
  1854. X
  1855. Xvoid
  1856. Xsetenv(nam,val)
  1857. Xchar *nam, *val;
  1858. X{
  1859. X    register int i=envix(nam);        /* where does it go? */
  1860. X
  1861. X    if (!environ[i]) {            /* does not exist yet */
  1862. X    if (firstsetenv) {        /* need we copy environment? */
  1863. X        int j;
  1864. X#ifndef lint
  1865. X        char **tmpenv = (char**)    /* point our wand at memory */
  1866. X        safemalloc((i+2) * sizeof(char*));
  1867. X#else
  1868. X        char **tmpenv = Null(char **);
  1869. X#endif /* lint */
  1870. X    
  1871. X        firstsetenv = FALSE;
  1872. X        for (j=0; j<i; j++)        /* copy environment */
  1873. X        tmpenv[j] = environ[j];
  1874. X        environ = tmpenv;        /* tell exec where it is now */
  1875. X    }
  1876. X#ifndef lint
  1877. X    else
  1878. X        environ = (char**) saferealloc((char*) environ,
  1879. X        (i+2) * sizeof(char*));
  1880. X                    /* just expand it a bit */
  1881. X#endif /* lint */
  1882. X    environ[i+1] = Nullch;    /* make sure it's null terminated */
  1883. X    }
  1884. X    environ[i] = safemalloc(strlen(nam) + strlen(val) + 2);
  1885. X                    /* this may or may not be in */
  1886. X                    /* the old environ structure */
  1887. X    sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
  1888. X}
  1889. X
  1890. Xint
  1891. Xenvix(nam)
  1892. Xchar *nam;
  1893. X{
  1894. X    register int i, len = strlen(nam);
  1895. X
  1896. X    for (i = 0; environ[i]; i++) {
  1897. X    if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
  1898. X        break;            /* strnEQ must come first to avoid */
  1899. X    }                    /* potential SEGV's */
  1900. X    return i;
  1901. X}
  1902. !STUFFY!FUNK!
  1903. echo Extracting t/op.push
  1904. sed >t/op.push <<'!STUFFY!FUNK!' -e 's/X//'
  1905. X#!./perl
  1906. X
  1907. X# $Header: op.push,v 3.0 89/10/18 15:30:48 lwall Locked $
  1908. X
  1909. Xprint "1..2\n";
  1910. X
  1911. X@x = (1,2,3);
  1912. Xpush(@x,@x);
  1913. Xif (join(':',@x) eq '1:2:3:1:2:3') {print "ok 1\n";} else {print "not ok 1\n";}
  1914. Xpush(x,4);
  1915. Xif (join(':',@x) eq '1:2:3:1:2:3:4') {print "ok 2\n";} else {print "not ok 2\n";}
  1916. !STUFFY!FUNK!
  1917. echo ""
  1918. echo "End of kit 15 (of 24)"
  1919. cat /dev/null >kit15isdone
  1920. run=''
  1921. config=''
  1922. for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24; do
  1923.     if test -f kit${iskit}isdone; then
  1924.     run="$run $iskit"
  1925.     else
  1926.     todo="$todo $iskit"
  1927.     fi
  1928. done
  1929. case $todo in
  1930.     '')
  1931.     echo "You have run all your kits.  Please read README and then type Configure."
  1932.     chmod 755 Configure
  1933.     ;;
  1934.     *)  echo "You have run$run."
  1935.     echo "You still need to run$todo."
  1936.     ;;
  1937. esac
  1938. : Someone might mail this, so...
  1939. exit
  1940.  
  1941.