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

  1. From: rsalz@uunet.uu.net (Rich Salz)
  2. Newsgroups: comp.sources.unix
  3. Subject: v20i102:  Perl, a language with features of C/sed/awk/shell/etc, Part19/24
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Larry Wall <lwall@jpl-devvax.jpl.nasa.gov>
  7. Posting-number: Volume 20, Issue 102
  8. Archive-name: perl3.0/part19
  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 19 (of 24).  If kit 19 is complete, the line"
  16. echo '"'"End of kit 19 (of 24)"'" will echo at the end.'
  17. echo ""
  18. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  19. mkdir x2p 2>/dev/null
  20. echo Extracting malloc.c
  21. sed >malloc.c <<'!STUFFY!FUNK!' -e 's/X//'
  22. X/* $Header: malloc.c,v 3.0 89/10/18 15:20:39 lwall Locked $
  23. X *
  24. X * $Log:    malloc.c,v $
  25. X * Revision 3.0  89/10/18  15:20:39  lwall
  26. X * 3.0 baseline
  27. X * 
  28. X */
  29. X
  30. X#ifndef lint
  31. Xstatic char sccsid[] = "@(#)malloc.c    4.3 (Berkeley) 9/16/83";
  32. X
  33. X#ifdef DEBUGGING
  34. X#define RCHECK
  35. X#endif
  36. X/*
  37. X * malloc.c (Caltech) 2/21/82
  38. X * Chris Kingsley, kingsley@cit-20.
  39. X *
  40. X * This is a very fast storage allocator.  It allocates blocks of a small 
  41. X * number of different sizes, and keeps free lists of each size.  Blocks that
  42. X * don't exactly fit are passed up to the next larger size.  In this 
  43. X * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long.
  44. X * This is designed for use in a program that uses vast quantities of memory,
  45. X * but bombs when it runs out. 
  46. X */
  47. X
  48. X#include "EXTERN.h"
  49. X#include "perl.h"
  50. X
  51. X/* I don't much care whether these are defined in sys/types.h--LAW */
  52. X
  53. X#define u_char unsigned char
  54. X#define u_int unsigned int
  55. X#define u_short unsigned short
  56. X
  57. X/*
  58. X * The overhead on a block is at least 4 bytes.  When free, this space
  59. X * contains a pointer to the next free block, and the bottom two bits must
  60. X * be zero.  When in use, the first byte is set to MAGIC, and the second
  61. X * byte is the size index.  The remaining bytes are for alignment.
  62. X * If range checking is enabled and the size of the block fits
  63. X * in two bytes, then the top two bytes hold the size of the requested block
  64. X * plus the range checking words, and the header word MINUS ONE.
  65. X */
  66. Xunion    overhead {
  67. X    union    overhead *ov_next;    /* when free */
  68. X#ifdef mips
  69. X    double  strut;            /* alignment problems */
  70. X#endif
  71. X    struct {
  72. X        u_char    ovu_magic;    /* magic number */
  73. X        u_char    ovu_index;    /* bucket # */
  74. X#ifdef RCHECK
  75. X        u_short    ovu_size;    /* actual block size */
  76. X        u_int    ovu_rmagic;    /* range magic number */
  77. X#endif
  78. X    } ovu;
  79. X#define    ov_magic    ovu.ovu_magic
  80. X#define    ov_index    ovu.ovu_index
  81. X#define    ov_size        ovu.ovu_size
  82. X#define    ov_rmagic    ovu.ovu_rmagic
  83. X};
  84. X
  85. X#define    MAGIC        0xff        /* magic # on accounting info */
  86. X#define OLDMAGIC    0x7f        /* same after a free() */
  87. X#define RMAGIC        0x55555555    /* magic # on range info */
  88. X#ifdef RCHECK
  89. X#define    RSLOP        sizeof (u_int)
  90. X#else
  91. X#define    RSLOP        0
  92. X#endif
  93. X
  94. X/*
  95. X * nextf[i] is the pointer to the next free block of size 2^(i+3).  The
  96. X * smallest allocatable block is 8 bytes.  The overhead information
  97. X * precedes the data area returned to the user.
  98. X */
  99. X#define    NBUCKETS 30
  100. Xstatic    union overhead *nextf[NBUCKETS];
  101. Xextern    char *sbrk();
  102. X
  103. X#ifdef MSTATS
  104. X/*
  105. X * nmalloc[i] is the difference between the number of mallocs and frees
  106. X * for a given block size.
  107. X */
  108. Xstatic    u_int nmalloc[NBUCKETS];
  109. X#include <stdio.h>
  110. X#endif
  111. X
  112. X#ifdef debug
  113. X#define    ASSERT(p)   if (!(p)) botch("p"); else
  114. Xstatic
  115. Xbotch(s)
  116. X    char *s;
  117. X{
  118. X
  119. X    printf("assertion botched: %s\n", s);
  120. X    abort();
  121. X}
  122. X#else
  123. X#define    ASSERT(p)
  124. X#endif
  125. X
  126. Xchar *
  127. Xmalloc(nbytes)
  128. X    register unsigned nbytes;
  129. X{
  130. X      register union overhead *p;
  131. X      register int bucket = 0;
  132. X      register unsigned shiftr;
  133. X
  134. X    /*
  135. X     * Convert amount of memory requested into
  136. X     * closest block size stored in hash buckets
  137. X     * which satisfies request.  Account for
  138. X     * space used per block for accounting.
  139. X     */
  140. X      nbytes += sizeof (union overhead) + RSLOP;
  141. X      nbytes = (nbytes + 3) &~ 3; 
  142. X      shiftr = (nbytes - 1) >> 2;
  143. X    /* apart from this loop, this is O(1) */
  144. X      while (shiftr >>= 1)
  145. X          bucket++;
  146. X    /*
  147. X     * If nothing in hash bucket right now,
  148. X     * request more memory from the system.
  149. X     */
  150. X      if (nextf[bucket] == NULL)    
  151. X          morecore(bucket);
  152. X      if ((p = (union overhead *)nextf[bucket]) == NULL)
  153. X          return (NULL);
  154. X    /* remove from linked list */
  155. X    if (*((int*)p) > 0x10000000)
  156. X#ifndef I286
  157. X        fprintf(stderr,"Corrupt malloc ptr 0x%x at 0x%x\n",*((int*)p),p);
  158. X#else
  159. X        fprintf(stderr,"Corrupt malloc ptr 0x%lx at 0x%lx\n",*((int*)p),p);
  160. X#endif
  161. X      nextf[bucket] = nextf[bucket]->ov_next;
  162. X    p->ov_magic = MAGIC;
  163. X    p->ov_index= bucket;
  164. X#ifdef MSTATS
  165. X      nmalloc[bucket]++;
  166. X#endif
  167. X#ifdef RCHECK
  168. X    /*
  169. X     * Record allocated size of block and
  170. X     * bound space with magic numbers.
  171. X     */
  172. X      if (nbytes <= 0x10000)
  173. X        p->ov_size = nbytes - 1;
  174. X    p->ov_rmagic = RMAGIC;
  175. X      *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
  176. X#endif
  177. X      return ((char *)(p + 1));
  178. X}
  179. X
  180. X/*
  181. X * Allocate more memory to the indicated bucket.
  182. X */
  183. Xstatic
  184. Xmorecore(bucket)
  185. X    register int bucket;
  186. X{
  187. X      register union overhead *op;
  188. X      register int rnu;       /* 2^rnu bytes will be requested */
  189. X      register int nblks;     /* become nblks blocks of the desired size */
  190. X    register int siz;
  191. X
  192. X      if (nextf[bucket])
  193. X          return;
  194. X    /*
  195. X     * Insure memory is allocated
  196. X     * on a page boundary.  Should
  197. X     * make getpageize call?
  198. X     */
  199. X      op = (union overhead *)sbrk(0);
  200. X#ifndef I286
  201. X      if ((int)op & 0x3ff)
  202. X          (void)sbrk(1024 - ((int)op & 0x3ff));
  203. X#else
  204. X    /* The sbrk(0) call on the I286 always returns the next segment */
  205. X#endif
  206. X
  207. X#ifndef I286
  208. X    /* take 2k unless the block is bigger than that */
  209. X      rnu = (bucket <= 8) ? 11 : bucket + 3;
  210. X#else
  211. X    /* take 16k unless the block is bigger than that 
  212. X       (80286s like large segments!)        */
  213. X      rnu = (bucket <= 11) ? 14 : bucket + 3;
  214. X#endif
  215. X      nblks = 1 << (rnu - (bucket + 3));  /* how many blocks to get */
  216. X      if (rnu < bucket)
  217. X        rnu = bucket;
  218. X    op = (union overhead *)sbrk(1 << rnu);
  219. X    /* no more room! */
  220. X      if ((int)op == -1)
  221. X          return;
  222. X    /*
  223. X     * Round up to minimum allocation size boundary
  224. X     * and deduct from block count to reflect.
  225. X     */
  226. X#ifndef I286
  227. X      if ((int)op & 7) {
  228. X          op = (union overhead *)(((int)op + 8) &~ 7);
  229. X          nblks--;
  230. X      }
  231. X#else
  232. X    /* Again, this should always be ok on an 80286 */
  233. X#endif
  234. X    /*
  235. X     * Add new memory allocated to that on
  236. X     * free list for this hash bucket.
  237. X     */
  238. X      nextf[bucket] = op;
  239. X      siz = 1 << (bucket + 3);
  240. X      while (--nblks > 0) {
  241. X        op->ov_next = (union overhead *)((caddr_t)op + siz);
  242. X        op = (union overhead *)((caddr_t)op + siz);
  243. X      }
  244. X}
  245. X
  246. Xfree(cp)
  247. X    char *cp;
  248. X{   
  249. X      register int size;
  250. X    register union overhead *op;
  251. X
  252. X      if (cp == NULL)
  253. X          return;
  254. X    op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
  255. X#ifdef debug
  256. X      ASSERT(op->ov_magic == MAGIC);        /* make sure it was in use */
  257. X#else
  258. X    if (op->ov_magic != MAGIC) {
  259. X        warn("%s free() ignored",
  260. X            op->ov_magic == OLDMAGIC ? "Duplicate" : "Bad");
  261. X        return;                /* sanity */
  262. X    }
  263. X    op->ov_magic = OLDMAGIC;
  264. X#endif
  265. X#ifdef RCHECK
  266. X      ASSERT(op->ov_rmagic == RMAGIC);
  267. X    if (op->ov_index <= 13)
  268. X        ASSERT(*(u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP) == RMAGIC);
  269. X#endif
  270. X      ASSERT(op->ov_index < NBUCKETS);
  271. X      size = op->ov_index;
  272. X    op->ov_next = nextf[size];
  273. X      nextf[size] = op;
  274. X#ifdef MSTATS
  275. X      nmalloc[size]--;
  276. X#endif
  277. X}
  278. X
  279. X/*
  280. X * When a program attempts "storage compaction" as mentioned in the
  281. X * old malloc man page, it realloc's an already freed block.  Usually
  282. X * this is the last block it freed; occasionally it might be farther
  283. X * back.  We have to search all the free lists for the block in order
  284. X * to determine its bucket: 1st we make one pass thru the lists
  285. X * checking only the first block in each; if that fails we search
  286. X * ``reall_srchlen'' blocks in each list for a match (the variable
  287. X * is extern so the caller can modify it).  If that fails we just copy
  288. X * however many bytes was given to realloc() and hope it's not huge.
  289. X */
  290. Xint reall_srchlen = 4;    /* 4 should be plenty, -1 =>'s whole list */
  291. X
  292. Xchar *
  293. Xrealloc(cp, nbytes)
  294. X    char *cp; 
  295. X    unsigned nbytes;
  296. X{   
  297. X      register u_int onb;
  298. X    union overhead *op;
  299. X      char *res;
  300. X    register int i;
  301. X    int was_alloced = 0;
  302. X
  303. X      if (cp == NULL)
  304. X          return (malloc(nbytes));
  305. X    op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
  306. X    if (op->ov_magic == MAGIC) {
  307. X        was_alloced++;
  308. X        i = op->ov_index;
  309. X    } else {
  310. X        /*
  311. X         * Already free, doing "compaction".
  312. X         *
  313. X         * Search for the old block of memory on the
  314. X         * free list.  First, check the most common
  315. X         * case (last element free'd), then (this failing)
  316. X         * the last ``reall_srchlen'' items free'd.
  317. X         * If all lookups fail, then assume the size of
  318. X         * the memory block being realloc'd is the
  319. X         * smallest possible.
  320. X         */
  321. X        if ((i = findbucket(op, 1)) < 0 &&
  322. X            (i = findbucket(op, reall_srchlen)) < 0)
  323. X            i = 0;
  324. X    }
  325. X    onb = (1 << (i + 3)) - sizeof (*op) - RSLOP;
  326. X    /* avoid the copy if same size block */
  327. X    if (was_alloced &&
  328. X        nbytes <= onb && nbytes > (onb >> 1) - sizeof(*op) - RSLOP) {
  329. X#ifdef RCHECK
  330. X        /*
  331. X         * Record new allocated size of block and
  332. X         * bound space with magic numbers.
  333. X         */
  334. X        if (op->ov_index <= 13) {
  335. X            /*
  336. X             * Convert amount of memory requested into
  337. X             * closest block size stored in hash buckets
  338. X             * which satisfies request.  Account for
  339. X             * space used per block for accounting.
  340. X             */
  341. X            nbytes += sizeof (union overhead) + RSLOP;
  342. X            nbytes = (nbytes + 3) &~ 3; 
  343. X            op->ov_size = nbytes - 1;
  344. X            *((u_int *)((caddr_t)op + nbytes - RSLOP)) = RMAGIC;
  345. X        }
  346. X#endif
  347. X        return(cp);
  348. X    }
  349. X      if ((res = malloc(nbytes)) == NULL)
  350. X          return (NULL);
  351. X      if (cp != res)            /* common optimization */
  352. X        (void)bcopy(cp, res, (int)((nbytes < onb) ? nbytes : onb));
  353. X      if (was_alloced)
  354. X        free(cp);
  355. X      return (res);
  356. X}
  357. X
  358. X/*
  359. X * Search ``srchlen'' elements of each free list for a block whose
  360. X * header starts at ``freep''.  If srchlen is -1 search the whole list.
  361. X * Return bucket number, or -1 if not found.
  362. X */
  363. Xstatic
  364. Xfindbucket(freep, srchlen)
  365. X    union overhead *freep;
  366. X    int srchlen;
  367. X{
  368. X    register union overhead *p;
  369. X    register int i, j;
  370. X
  371. X    for (i = 0; i < NBUCKETS; i++) {
  372. X        j = 0;
  373. X        for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
  374. X            if (p == freep)
  375. X                return (i);
  376. X            j++;
  377. X        }
  378. X    }
  379. X    return (-1);
  380. X}
  381. X
  382. X#ifdef MSTATS
  383. X/*
  384. X * mstats - print out statistics about malloc
  385. X * 
  386. X * Prints two lines of numbers, one showing the length of the free list
  387. X * for each size category, the second showing the number of mallocs -
  388. X * frees for each size category.
  389. X */
  390. Xmstats(s)
  391. X    char *s;
  392. X{
  393. X      register int i, j;
  394. X      register union overhead *p;
  395. X      int totfree = 0,
  396. X      totused = 0;
  397. X
  398. X      fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s);
  399. X      for (i = 0; i < NBUCKETS; i++) {
  400. X          for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
  401. X              ;
  402. X          fprintf(stderr, " %d", j);
  403. X          totfree += j * (1 << (i + 3));
  404. X      }
  405. X      fprintf(stderr, "\nused:\t");
  406. X      for (i = 0; i < NBUCKETS; i++) {
  407. X          fprintf(stderr, " %d", nmalloc[i]);
  408. X          totused += nmalloc[i] * (1 << (i + 3));
  409. X      }
  410. X      fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n",
  411. X        totused, totfree);
  412. X}
  413. X#endif
  414. X#endif /* lint */
  415. !STUFFY!FUNK!
  416. echo Extracting x2p/str.c
  417. sed >x2p/str.c <<'!STUFFY!FUNK!' -e 's/X//'
  418. X/* $Header: str.c,v 3.0 89/10/18 15:35:18 lwall Locked $
  419. X *
  420. X *    Copyright (c) 1989, Larry Wall
  421. X *
  422. X *    You may distribute under the terms of the GNU General Public License
  423. X *    as specified in the README file that comes with the perl 3.0 kit.
  424. X *
  425. X * $Log:    str.c,v $
  426. X * Revision 3.0  89/10/18  15:35:18  lwall
  427. X * 3.0 baseline
  428. X * 
  429. X */
  430. X
  431. X#include "handy.h"
  432. X#include "EXTERN.h"
  433. X#include "util.h"
  434. X#include "a2p.h"
  435. X
  436. Xstr_numset(str,num)
  437. Xregister STR *str;
  438. Xdouble num;
  439. X{
  440. X    str->str_nval = num;
  441. X    str->str_pok = 0;        /* invalidate pointer */
  442. X    str->str_nok = 1;        /* validate number */
  443. X}
  444. X
  445. Xchar *
  446. Xstr_2ptr(str)
  447. Xregister STR *str;
  448. X{
  449. X    register char *s;
  450. X
  451. X    if (!str)
  452. X    return "";
  453. X    GROWSTR(&(str->str_ptr), &(str->str_len), 24);
  454. X    s = str->str_ptr;
  455. X    if (str->str_nok) {
  456. X    sprintf(s,"%.20g",str->str_nval);
  457. X    while (*s) s++;
  458. X    }
  459. X    *s = '\0';
  460. X    str->str_cur = s - str->str_ptr;
  461. X    str->str_pok = 1;
  462. X#ifdef DEBUGGING
  463. X    if (debug & 32)
  464. X    fprintf(stderr,"0x%lx ptr(%s)\n",str,str->str_ptr);
  465. X#endif
  466. X    return str->str_ptr;
  467. X}
  468. X
  469. Xdouble
  470. Xstr_2num(str)
  471. Xregister STR *str;
  472. X{
  473. X    if (!str)
  474. X    return 0.0;
  475. X    if (str->str_len && str->str_pok)
  476. X    str->str_nval = atof(str->str_ptr);
  477. X    else
  478. X    str->str_nval = 0.0;
  479. X    str->str_nok = 1;
  480. X#ifdef DEBUGGING
  481. X    if (debug & 32)
  482. X    fprintf(stderr,"0x%lx num(%g)\n",str,str->str_nval);
  483. X#endif
  484. X    return str->str_nval;
  485. X}
  486. X
  487. Xstr_sset(dstr,sstr)
  488. XSTR *dstr;
  489. Xregister STR *sstr;
  490. X{
  491. X    if (!sstr)
  492. X    str_nset(dstr,No,0);
  493. X    else if (sstr->str_nok)
  494. X    str_numset(dstr,sstr->str_nval);
  495. X    else if (sstr->str_pok)
  496. X    str_nset(dstr,sstr->str_ptr,sstr->str_cur);
  497. X    else
  498. X    str_nset(dstr,"",0);
  499. X}
  500. X
  501. Xstr_nset(str,ptr,len)
  502. Xregister STR *str;
  503. Xregister char *ptr;
  504. Xregister int len;
  505. X{
  506. X    GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
  507. X    bcopy(ptr,str->str_ptr,len);
  508. X    str->str_cur = len;
  509. X    *(str->str_ptr+str->str_cur) = '\0';
  510. X    str->str_nok = 0;        /* invalidate number */
  511. X    str->str_pok = 1;        /* validate pointer */
  512. X}
  513. X
  514. Xstr_set(str,ptr)
  515. Xregister STR *str;
  516. Xregister char *ptr;
  517. X{
  518. X    register int len;
  519. X
  520. X    if (!ptr)
  521. X    ptr = "";
  522. X    len = strlen(ptr);
  523. X    GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
  524. X    bcopy(ptr,str->str_ptr,len+1);
  525. X    str->str_cur = len;
  526. X    str->str_nok = 0;        /* invalidate number */
  527. X    str->str_pok = 1;        /* validate pointer */
  528. X}
  529. X
  530. Xstr_chop(str,ptr)    /* like set but assuming ptr is in str */
  531. Xregister STR *str;
  532. Xregister char *ptr;
  533. X{
  534. X    if (!(str->str_pok))
  535. X    str_2ptr(str);
  536. X    str->str_cur -= (ptr - str->str_ptr);
  537. X    bcopy(ptr,str->str_ptr, str->str_cur + 1);
  538. X    str->str_nok = 0;        /* invalidate number */
  539. X    str->str_pok = 1;        /* validate pointer */
  540. X}
  541. X
  542. Xstr_ncat(str,ptr,len)
  543. Xregister STR *str;
  544. Xregister char *ptr;
  545. Xregister int len;
  546. X{
  547. X    if (!(str->str_pok))
  548. X    str_2ptr(str);
  549. X    GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
  550. X    bcopy(ptr,str->str_ptr+str->str_cur,len);
  551. X    str->str_cur += len;
  552. X    *(str->str_ptr+str->str_cur) = '\0';
  553. X    str->str_nok = 0;        /* invalidate number */
  554. X    str->str_pok = 1;        /* validate pointer */
  555. X}
  556. X
  557. Xstr_scat(dstr,sstr)
  558. XSTR *dstr;
  559. Xregister STR *sstr;
  560. X{
  561. X    if (!(sstr->str_pok))
  562. X    str_2ptr(sstr);
  563. X    if (sstr)
  564. X    str_ncat(dstr,sstr->str_ptr,sstr->str_cur);
  565. X}
  566. X
  567. Xstr_cat(str,ptr)
  568. Xregister STR *str;
  569. Xregister char *ptr;
  570. X{
  571. X    register int len;
  572. X
  573. X    if (!ptr)
  574. X    return;
  575. X    if (!(str->str_pok))
  576. X    str_2ptr(str);
  577. X    len = strlen(ptr);
  578. X    GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
  579. X    bcopy(ptr,str->str_ptr+str->str_cur,len+1);
  580. X    str->str_cur += len;
  581. X    str->str_nok = 0;        /* invalidate number */
  582. X    str->str_pok = 1;        /* validate pointer */
  583. X}
  584. X
  585. Xchar *
  586. Xstr_append_till(str,from,delim,keeplist)
  587. Xregister STR *str;
  588. Xregister char *from;
  589. Xregister int delim;
  590. Xchar *keeplist;
  591. X{
  592. X    register char *to;
  593. X    register int len;
  594. X
  595. X    if (!from)
  596. X    return Nullch;
  597. X    len = strlen(from);
  598. X    GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
  599. X    str->str_nok = 0;        /* invalidate number */
  600. X    str->str_pok = 1;        /* validate pointer */
  601. X    to = str->str_ptr+str->str_cur;
  602. X    for (; *from; from++,to++) {
  603. X    if (*from == '\\' && from[1] && delim != '\\') {
  604. X        if (!keeplist) {
  605. X        if (from[1] == delim || from[1] == '\\')
  606. X            from++;
  607. X        else
  608. X            *to++ = *from++;
  609. X        }
  610. X        else if (index(keeplist,from[1]))
  611. X        *to++ = *from++;
  612. X        else
  613. X        from++;
  614. X    }
  615. X    else if (*from == delim)
  616. X        break;
  617. X    *to = *from;
  618. X    }
  619. X    *to = '\0';
  620. X    str->str_cur = to - str->str_ptr;
  621. X    return from;
  622. X}
  623. X
  624. XSTR *
  625. Xstr_new(len)
  626. Xint len;
  627. X{
  628. X    register STR *str;
  629. X    
  630. X    if (freestrroot) {
  631. X    str = freestrroot;
  632. X    freestrroot = str->str_link.str_next;
  633. X    }
  634. X    else {
  635. X    str = (STR *) safemalloc(sizeof(STR));
  636. X    bzero((char*)str,sizeof(STR));
  637. X    }
  638. X    if (len)
  639. X    GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
  640. X    return str;
  641. X}
  642. X
  643. Xvoid
  644. Xstr_grow(str,len)
  645. Xregister STR *str;
  646. Xint len;
  647. X{
  648. X    if (len && str)
  649. X    GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
  650. X}
  651. X
  652. X/* make str point to what nstr did */
  653. X
  654. Xvoid
  655. Xstr_replace(str,nstr)
  656. Xregister STR *str;
  657. Xregister STR *nstr;
  658. X{
  659. X    safefree(str->str_ptr);
  660. X    str->str_ptr = nstr->str_ptr;
  661. X    str->str_len = nstr->str_len;
  662. X    str->str_cur = nstr->str_cur;
  663. X    str->str_pok = nstr->str_pok;
  664. X    if (str->str_nok = nstr->str_nok)
  665. X    str->str_nval = nstr->str_nval;
  666. X    safefree((char*)nstr);
  667. X}
  668. X
  669. Xvoid
  670. Xstr_free(str)
  671. Xregister STR *str;
  672. X{
  673. X    if (!str)
  674. X    return;
  675. X    if (str->str_len)
  676. X    str->str_ptr[0] = '\0';
  677. X    str->str_cur = 0;
  678. X    str->str_nok = 0;
  679. X    str->str_pok = 0;
  680. X    str->str_link.str_next = freestrroot;
  681. X    freestrroot = str;
  682. X}
  683. X
  684. Xstr_len(str)
  685. Xregister STR *str;
  686. X{
  687. X    if (!str)
  688. X    return 0;
  689. X    if (!(str->str_pok))
  690. X    str_2ptr(str);
  691. X    if (str->str_len)
  692. X    return str->str_cur;
  693. X    else
  694. X    return 0;
  695. X}
  696. X
  697. Xchar *
  698. Xstr_gets(str,fp)
  699. Xregister STR *str;
  700. Xregister FILE *fp;
  701. X{
  702. X#ifdef STDSTDIO        /* Here is some breathtakingly efficient cheating */
  703. X
  704. X    register char *bp;        /* we're going to steal some values */
  705. X    register int cnt;        /*  from the stdio struct and put EVERYTHING */
  706. X    register STDCHAR *ptr;    /*   in the innermost loop into registers */
  707. X    register char newline = '\n';    /* (assuming at least 6 registers) */
  708. X    int i;
  709. X    int bpx;
  710. X
  711. X    cnt = fp->_cnt;            /* get count into register */
  712. X    str->str_nok = 0;            /* invalidate number */
  713. X    str->str_pok = 1;            /* validate pointer */
  714. X    if (str->str_len <= cnt)        /* make sure we have the room */
  715. X    GROWSTR(&(str->str_ptr), &(str->str_len), cnt+1);
  716. X    bp = str->str_ptr;            /* move these two too to registers */
  717. X    ptr = fp->_ptr;
  718. X    for (;;) {
  719. X    while (--cnt >= 0) {
  720. X        if ((*bp++ = *ptr++) == newline)
  721. X        if (bp <= str->str_ptr || bp[-2] != '\\')
  722. X            goto thats_all_folks;
  723. X        else {
  724. X            line++;
  725. X            bp -= 2;
  726. X        }
  727. X    }
  728. X    
  729. X    fp->_cnt = cnt;            /* deregisterize cnt and ptr */
  730. X    fp->_ptr = ptr;
  731. X    i = _filbuf(fp);        /* get more characters */
  732. X    cnt = fp->_cnt;
  733. X    ptr = fp->_ptr;            /* reregisterize cnt and ptr */
  734. X
  735. X    bpx = bp - str->str_ptr;    /* prepare for possible relocation */
  736. X    GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + cnt + 1);
  737. X    bp = str->str_ptr + bpx;    /* reconstitute our pointer */
  738. X
  739. X    if (i == newline) {        /* all done for now? */
  740. X        *bp++ = i;
  741. X        goto thats_all_folks;
  742. X    }
  743. X    else if (i == EOF)        /* all done for ever? */
  744. X        goto thats_all_folks;
  745. X    *bp++ = i;            /* now go back to screaming loop */
  746. X    }
  747. X
  748. Xthats_all_folks:
  749. X    fp->_cnt = cnt;            /* put these back or we're in trouble */
  750. X    fp->_ptr = ptr;
  751. X    *bp = '\0';
  752. X    str->str_cur = bp - str->str_ptr;    /* set length */
  753. X
  754. X#else /* !STDSTDIO */    /* The big, slow, and stupid way */
  755. X
  756. X    static char buf[4192];
  757. X
  758. X    if (fgets(buf, sizeof buf, fp) != Nullch)
  759. X    str_set(str, buf);
  760. X    else
  761. X    str_set(str, No);
  762. X
  763. X#endif /* STDSTDIO */
  764. X
  765. X    return str->str_cur ? str->str_ptr : Nullch;
  766. X}
  767. X
  768. Xvoid
  769. Xstr_inc(str)
  770. Xregister STR *str;
  771. X{
  772. X    register char *d;
  773. X
  774. X    if (!str)
  775. X    return;
  776. X    if (str->str_nok) {
  777. X    str->str_nval += 1.0;
  778. X    str->str_pok = 0;
  779. X    return;
  780. X    }
  781. X    if (!str->str_pok) {
  782. X    str->str_nval = 1.0;
  783. X    str->str_nok = 1;
  784. X    return;
  785. X    }
  786. X    for (d = str->str_ptr; *d && *d != '.'; d++) ;
  787. X    d--;
  788. X    if (!isdigit(*str->str_ptr) || !isdigit(*d) ) {
  789. X        str_numset(str,atof(str->str_ptr) + 1.0);  /* punt */
  790. X    return;
  791. X    }
  792. X    while (d >= str->str_ptr) {
  793. X    if (++*d <= '9')
  794. X        return;
  795. X    *(d--) = '0';
  796. X    }
  797. X    /* oh,oh, the number grew */
  798. X    GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + 2);
  799. X    str->str_cur++;
  800. X    for (d = str->str_ptr + str->str_cur; d > str->str_ptr; d--)
  801. X    *d = d[-1];
  802. X    *d = '1';
  803. X}
  804. X
  805. Xvoid
  806. Xstr_dec(str)
  807. Xregister STR *str;
  808. X{
  809. X    register char *d;
  810. X
  811. X    if (!str)
  812. X    return;
  813. X    if (str->str_nok) {
  814. X    str->str_nval -= 1.0;
  815. X    str->str_pok = 0;
  816. X    return;
  817. X    }
  818. X    if (!str->str_pok) {
  819. X    str->str_nval = -1.0;
  820. X    str->str_nok = 1;
  821. X    return;
  822. X    }
  823. X    for (d = str->str_ptr; *d && *d != '.'; d++) ;
  824. X    d--;
  825. X    if (!isdigit(*str->str_ptr) || !isdigit(*d) || (*d == '0' && d == str->str_ptr)) {
  826. X        str_numset(str,atof(str->str_ptr) - 1.0);  /* punt */
  827. X    return;
  828. X    }
  829. X    while (d >= str->str_ptr) {
  830. X    if (--*d >= '0')
  831. X        return;
  832. X    *(d--) = '9';
  833. X    }
  834. X}
  835. X
  836. X/* make a string that will exist for the duration of the expression eval */
  837. X
  838. XSTR *
  839. Xstr_static(oldstr)
  840. XSTR *oldstr;
  841. X{
  842. X    register STR *str = str_new(0);
  843. X    static long tmps_size = -1;
  844. X
  845. X    str_sset(str,oldstr);
  846. X    if (++tmps_max > tmps_size) {
  847. X    tmps_size = tmps_max;
  848. X    if (!(tmps_size & 127)) {
  849. X        if (tmps_size)
  850. X        tmps_list = (STR**)saferealloc((char*)tmps_list,
  851. X            (tmps_size + 128) * sizeof(STR*) );
  852. X        else
  853. X        tmps_list = (STR**)safemalloc(128 * sizeof(char*));
  854. X    }
  855. X    }
  856. X    tmps_list[tmps_max] = str;
  857. X    return str;
  858. X}
  859. X
  860. XSTR *
  861. Xstr_make(s)
  862. Xchar *s;
  863. X{
  864. X    register STR *str = str_new(0);
  865. X
  866. X    str_set(str,s);
  867. X    return str;
  868. X}
  869. X
  870. XSTR *
  871. Xstr_nmake(n)
  872. Xdouble n;
  873. X{
  874. X    register STR *str = str_new(0);
  875. X
  876. X    str_numset(str,n);
  877. X    return str;
  878. X}
  879. !STUFFY!FUNK!
  880. echo Extracting x2p/a2p.y
  881. sed >x2p/a2p.y <<'!STUFFY!FUNK!' -e 's/X//'
  882. X%{
  883. X/* $Header: a2p.y,v 3.0 89/10/18 15:34:29 lwall Locked $
  884. X *
  885. X *    Copyright (c) 1989, Larry Wall
  886. X *
  887. X *    You may distribute under the terms of the GNU General Public License
  888. X *    as specified in the README file that comes with the perl 3.0 kit.
  889. X *
  890. X * $Log:    a2p.y,v $
  891. X * Revision 3.0  89/10/18  15:34:29  lwall
  892. X * 3.0 baseline
  893. X * 
  894. X */
  895. X
  896. X#include "INTERN.h"
  897. X#include "a2p.h"
  898. X
  899. Xint root;
  900. Xint begins = Nullop;
  901. Xint ends = Nullop;
  902. X
  903. X%}
  904. X%token BEGIN END
  905. X%token REGEX
  906. X%token SEMINEW NEWLINE COMMENT
  907. X%token FUN1 FUNN GRGR
  908. X%token PRINT PRINTF SPRINTF SPLIT
  909. X%token IF ELSE WHILE FOR IN
  910. X%token EXIT NEXT BREAK CONTINUE RET
  911. X%token GETLINE DO SUB GSUB MATCH
  912. X%token FUNCTION USERFUN DELETE
  913. X
  914. X%right ASGNOP
  915. X%right '?' ':'
  916. X%left OROR
  917. X%left ANDAND
  918. X%left IN
  919. X%left NUMBER VAR SUBSTR INDEX
  920. X%left MATCHOP
  921. X%left RELOP '<' '>'
  922. X%left OR
  923. X%left STRING
  924. X%left '+' '-'
  925. X%left '*' '/' '%'
  926. X%right UMINUS
  927. X%left NOT
  928. X%right '^'
  929. X%left INCR DECR
  930. X%left FIELD VFIELD
  931. X
  932. X%%
  933. X
  934. Xprogram    : junk hunks
  935. X        { root = oper4(OPROG,$1,begins,$2,ends); }
  936. X    ;
  937. X
  938. Xbegin    : BEGIN '{' maybe states '}' junk
  939. X        { begins = oper4(OJUNK,begins,$3,$4,$6); in_begin = FALSE;
  940. X            $$ = Nullop; }
  941. X    ;
  942. X
  943. Xend    : END '{' maybe states '}'
  944. X        { ends = oper3(OJUNK,ends,$3,$4); $$ = Nullop; }
  945. X    | end NEWLINE
  946. X        { $$ = $1; }
  947. X    ;
  948. X
  949. Xhunks    : hunks hunk junk
  950. X        { $$ = oper3(OHUNKS,$1,$2,$3); }
  951. X    | /* NULL */
  952. X        { $$ = Nullop; }
  953. X    ;
  954. X
  955. Xhunk    : patpat
  956. X        { $$ = oper1(OHUNK,$1); need_entire = TRUE; }
  957. X    | patpat '{' maybe states '}'
  958. X        { $$ = oper2(OHUNK,$1,oper2(OJUNK,$3,$4)); }
  959. X    | FUNCTION USERFUN '(' arg_list ')' maybe '{' maybe states '}'
  960. X        { fixfargs($2,$4,0); $$ = oper5(OUSERDEF,$2,$4,$6,$8,$9); }
  961. X    | '{' maybe states '}'
  962. X        { $$ = oper2(OHUNK,Nullop,oper2(OJUNK,$2,$3)); }
  963. X    | begin
  964. X    | end
  965. X    ;
  966. X
  967. Xarg_list: expr_list
  968. X        { $$ = rememberargs($$); }
  969. X    ;
  970. X
  971. Xpatpat    : pat
  972. X        { $$ = oper1(OPAT,$1); }
  973. X    | pat ',' pat
  974. X        { $$ = oper2(ORANGE,$1,$3); }
  975. X    ;
  976. X
  977. Xpat    : match
  978. X    | rel
  979. X    | compound_pat
  980. X    ;
  981. X
  982. Xcompound_pat
  983. X    : '(' compound_pat ')'
  984. X        { $$ = oper1(OPPAREN,$2); }
  985. X    | pat ANDAND maybe pat
  986. X        { $$ = oper3(OPANDAND,$1,$3,$4); }
  987. X    | pat OROR maybe pat
  988. X        { $$ = oper3(OPOROR,$1,$3,$4); }
  989. X    | NOT pat
  990. X        { $$ = oper1(OPNOT,$2); }
  991. X    ;
  992. X
  993. Xcond    : expr
  994. X    | match
  995. X    | rel
  996. X    | compound_cond
  997. X    ;
  998. X
  999. Xcompound_cond
  1000. X    : '(' compound_cond ')'
  1001. X        { $$ = oper1(OCPAREN,$2); }
  1002. X    | cond ANDAND maybe cond
  1003. X        { $$ = oper3(OCANDAND,$1,$3,$4); }
  1004. X    | cond OROR maybe cond
  1005. X        { $$ = oper3(OCOROR,$1,$3,$4); }
  1006. X    | NOT cond
  1007. X        { $$ = oper1(OCNOT,$2); }
  1008. X    ;
  1009. X
  1010. Xrel    : expr RELOP expr
  1011. X        { $$ = oper3(ORELOP,$2,$1,$3); }
  1012. X    | expr '>' expr
  1013. X        { $$ = oper3(ORELOP,string(">",1),$1,$3); }
  1014. X    | expr '<' expr
  1015. X        { $$ = oper3(ORELOP,string("<",1),$1,$3); }
  1016. X    | '(' rel ')'
  1017. X        { $$ = oper1(ORPAREN,$2); }
  1018. X    ;
  1019. X
  1020. Xmatch    : expr MATCHOP expr
  1021. X        { $$ = oper3(OMATCHOP,$2,$1,$3); }
  1022. X    | expr MATCHOP REGEX
  1023. X        { $$ = oper3(OMATCHOP,$2,$1,oper1(OREGEX,$3)); }
  1024. X    | REGEX        %prec MATCHOP
  1025. X        { $$ = oper1(OREGEX,$1); }
  1026. X    | '(' match ')'
  1027. X        { $$ = oper1(OMPAREN,$2); }
  1028. X    ;
  1029. X
  1030. Xexpr    : term
  1031. X        { $$ = $1; }
  1032. X    | expr term
  1033. X        { $$ = oper2(OCONCAT,$1,$2); }
  1034. X    | variable ASGNOP expr
  1035. X        { $$ = oper3(OASSIGN,$2,$1,$3);
  1036. X            if ((ops[$1].ival & 255) == OFLD)
  1037. X                lval_field = TRUE;
  1038. X            if ((ops[$1].ival & 255) == OVFLD)
  1039. X                lval_field = TRUE;
  1040. X        }
  1041. X    ;
  1042. X
  1043. Xterm    : variable
  1044. X        { $$ = $1; }
  1045. X    | NUMBER
  1046. X        { $$ = oper1(ONUM,$1); }
  1047. X    | STRING
  1048. X        { $$ = oper1(OSTR,$1); }
  1049. X    | term '+' term
  1050. X        { $$ = oper2(OADD,$1,$3); }
  1051. X    | term '-' term
  1052. X        { $$ = oper2(OSUBTRACT,$1,$3); }
  1053. X    | term '*' term
  1054. X        { $$ = oper2(OMULT,$1,$3); }
  1055. X    | term '/' term
  1056. X        { $$ = oper2(ODIV,$1,$3); }
  1057. X    | term '%' term
  1058. X        { $$ = oper2(OMOD,$1,$3); }
  1059. X    | term '^' term
  1060. X        { $$ = oper2(OPOW,$1,$3); }
  1061. X    | term IN VAR
  1062. X        { $$ = oper2(ODEFINED,aryrefarg($3),$1); }
  1063. X    | term '?' term ':' term
  1064. X        { $$ = oper2(OCOND,$1,$3,$5); }
  1065. X    | variable INCR
  1066. X        { $$ = oper1(OPOSTINCR,$1); }
  1067. X    | variable DECR
  1068. X        { $$ = oper1(OPOSTDECR,$1); }
  1069. X    | INCR variable
  1070. X        { $$ = oper1(OPREINCR,$2); }
  1071. X    | DECR variable
  1072. X        { $$ = oper1(OPREDECR,$2); }
  1073. X    | '-' term %prec UMINUS
  1074. X        { $$ = oper1(OUMINUS,$2); }
  1075. X    | '+' term %prec UMINUS
  1076. X        { $$ = oper1(OUPLUS,$2); }
  1077. X    | '(' expr ')'
  1078. X        { $$ = oper1(OPAREN,$2); }
  1079. X    | GETLINE
  1080. X        { $$ = oper0(OGETLINE); }
  1081. X    | GETLINE VAR
  1082. X        { $$ = oper1(OGETLINE,$2); }
  1083. X    | GETLINE '<' expr
  1084. X        { $$ = oper3(OGETLINE,Nullop,string("<",1),$3);
  1085. X            if (ops[$3].ival != OSTR + (1<<8)) do_fancy_opens = TRUE; }
  1086. X    | GETLINE VAR '<' expr
  1087. X        { $$ = oper3(OGETLINE,$2,string("<",1),$4);
  1088. X            if (ops[$4].ival != OSTR + (1<<8)) do_fancy_opens = TRUE; }
  1089. X    | term 'p' GETLINE
  1090. X        { $$ = oper3(OGETLINE,Nullop,string("|",1),$1);
  1091. X            if (ops[$1].ival != OSTR + (1<<8)) do_fancy_opens = TRUE; }
  1092. X    | term 'p' GETLINE VAR
  1093. X        { $$ = oper3(OGETLINE,$4,string("|",1),$1);
  1094. X            if (ops[$1].ival != OSTR + (1<<8)) do_fancy_opens = TRUE; }
  1095. X    | FUN1
  1096. X        { $$ = oper0($1); need_entire = do_chop = TRUE; }
  1097. X    | FUN1 '(' ')'
  1098. X        { $$ = oper1($1,Nullop); need_entire = do_chop = TRUE; }
  1099. X    | FUN1 '(' expr ')'
  1100. X        { $$ = oper1($1,$3); }
  1101. X    | FUNN '(' expr_list ')'
  1102. X        { $$ = oper1($1,$3); }
  1103. X    | USERFUN '(' expr_list ')'
  1104. X        { $$ = oper2(OUSERFUN,$1,$3); }
  1105. X    | SPRINTF expr_list
  1106. X        { $$ = oper1(OSPRINTF,$2); }
  1107. X    | SUBSTR '(' expr ',' expr ',' expr ')'
  1108. X        { $$ = oper3(OSUBSTR,$3,$5,$7); }
  1109. X    | SUBSTR '(' expr ',' expr ')'
  1110. X        { $$ = oper2(OSUBSTR,$3,$5); }
  1111. X    | SPLIT '(' expr ',' VAR ',' expr ')'
  1112. X        { $$ = oper3(OSPLIT,$3,aryrefarg(numary($5)),$7); }
  1113. X    | SPLIT '(' expr ',' VAR ')'
  1114. X        { $$ = oper2(OSPLIT,$3,aryrefarg(numary($5))); }
  1115. X    | INDEX '(' expr ',' expr ')'
  1116. X        { $$ = oper2(OINDEX,$3,$5); }
  1117. X    | MATCH '(' expr ',' REGEX ')'
  1118. X        { $$ = oper2(OMATCH,$3,oper1(OREGEX,$5)); }
  1119. X    | MATCH '(' expr ',' expr ')'
  1120. X        { $$ = oper2(OMATCH,$3,$5); }
  1121. X    | SUB '(' expr ',' expr ')'
  1122. X        { $$ = oper2(OSUB,$3,$5); }
  1123. X    | SUB '(' REGEX ',' expr ')'
  1124. X        { $$ = oper2(OSUB,oper1(OREGEX,$3),$5); }
  1125. X    | GSUB '(' expr ',' expr ')'
  1126. X        { $$ = oper2(OGSUB,$3,$5); }
  1127. X    | GSUB '(' REGEX ',' expr ')'
  1128. X        { $$ = oper2(OGSUB,oper1(OREGEX,$3),$5); }
  1129. X    | SUB '(' expr ',' expr ',' expr ')'
  1130. X        { $$ = oper3(OSUB,$3,$5,$7); }
  1131. X    | SUB '(' REGEX ',' expr ',' expr ')'
  1132. X        { $$ = oper3(OSUB,oper1(OREGEX,$3),$5,$7); }
  1133. X    | GSUB '(' expr ',' expr ',' expr ')'
  1134. X        { $$ = oper3(OGSUB,$3,$5,$7); }
  1135. X    | GSUB '(' REGEX ',' expr ',' expr ')'
  1136. X        { $$ = oper3(OGSUB,oper1(OREGEX,$3),$5,$7); }
  1137. X    ;
  1138. X
  1139. Xvariable: VAR
  1140. X        { $$ = oper1(OVAR,$1); }
  1141. X    | VAR '[' expr_list ']'
  1142. X        { $$ = oper2(OVAR,aryrefarg($1),$3); }
  1143. X    | FIELD
  1144. X        { $$ = oper1(OFLD,$1); }
  1145. X    | VFIELD term
  1146. X        { $$ = oper1(OVFLD,$2); }
  1147. X    ;
  1148. X
  1149. Xexpr_list
  1150. X    : expr
  1151. X    | clist
  1152. X    | /* NULL */
  1153. X        { $$ = Nullop; }
  1154. X    ;
  1155. X
  1156. Xclist    : expr ',' maybe expr
  1157. X        { $$ = oper3(OCOMMA,$1,$3,$4); }
  1158. X    | clist ',' maybe expr
  1159. X        { $$ = oper3(OCOMMA,$1,$3,$4); }
  1160. X    | '(' clist ')'        /* these parens are invisible */
  1161. X        { $$ = $2; }
  1162. X    ;
  1163. X
  1164. Xjunk    : junk hunksep
  1165. X        { $$ = oper2(OJUNK,$1,$2); }
  1166. X    | /* NULL */
  1167. X        { $$ = Nullop; }
  1168. X    ;
  1169. X
  1170. Xhunksep : ';'
  1171. X        { $$ = oper2(OJUNK,oper0(OSEMICOLON),oper0(ONEWLINE)); }
  1172. X    | SEMINEW
  1173. X        { $$ = oper2(OJUNK,oper0(OSEMICOLON),oper0(ONEWLINE)); }
  1174. X    | NEWLINE
  1175. X        { $$ = oper0(ONEWLINE); }
  1176. X    | COMMENT
  1177. X        { $$ = oper1(OCOMMENT,$1); }
  1178. X    ;
  1179. X
  1180. Xmaybe    : maybe nlstuff
  1181. X        { $$ = oper2(OJUNK,$1,$2); }
  1182. X    | /* NULL */
  1183. X        { $$ = Nullop; }
  1184. X    ;
  1185. X
  1186. Xnlstuff : NEWLINE
  1187. X        { $$ = oper0(ONEWLINE); }
  1188. X    | COMMENT
  1189. X        { $$ = oper1(OCOMMENT,$1); }
  1190. X    ;
  1191. X
  1192. Xseparator
  1193. X    : ';' maybe
  1194. X        { $$ = oper2(OJUNK,oper0(OSEMICOLON),$2); }
  1195. X    | SEMINEW maybe
  1196. X        { $$ = oper2(OJUNK,oper0(OSNEWLINE),$2); }
  1197. X    | NEWLINE maybe
  1198. X        { $$ = oper2(OJUNK,oper0(OSNEWLINE),$2); }
  1199. X    | COMMENT maybe
  1200. X        { $$ = oper2(OJUNK,oper1(OSCOMMENT,$1),$2); }
  1201. X    ;
  1202. X
  1203. Xstates    : states statement
  1204. X        { $$ = oper2(OSTATES,$1,$2); }
  1205. X    | /* NULL */
  1206. X        { $$ = Nullop; }
  1207. X    ;
  1208. X
  1209. Xstatement
  1210. X    : simple separator maybe
  1211. X        { $$ = oper2(OJUNK,oper2(OSTATE,$1,$2),$3); }
  1212. X    | ';' maybe
  1213. X        { $$ = oper2(OSTATE,Nullop,oper2(OJUNK,oper0(OSEMICOLON),$2)); }
  1214. X    | SEMINEW maybe
  1215. X        { $$ = oper2(OSTATE,Nullop,oper2(OJUNK,oper0(OSNEWLINE),$2)); }
  1216. X    | compound
  1217. X    ;
  1218. X
  1219. Xsimpnull: simple
  1220. X    | /* NULL */
  1221. X        { $$ = Nullop; }
  1222. X    ;
  1223. X
  1224. Xsimple
  1225. X    : expr
  1226. X    | PRINT expr_list redir expr
  1227. X        { $$ = oper3(OPRINT,$2,$3,$4);
  1228. X            do_opens = TRUE;
  1229. X            saw_ORS = saw_OFS = TRUE;
  1230. X            if (!$2) need_entire = TRUE;
  1231. X            if (ops[$4].ival != OSTR + (1<<8)) do_fancy_opens = TRUE; }
  1232. X    | PRINT expr_list
  1233. X        { $$ = oper1(OPRINT,$2);
  1234. X            if (!$2) need_entire = TRUE;
  1235. X            saw_ORS = saw_OFS = TRUE;
  1236. X        }
  1237. X    | PRINTF expr_list redir expr
  1238. X        { $$ = oper3(OPRINTF,$2,$3,$4);
  1239. X            do_opens = TRUE;
  1240. X            if (!$2) need_entire = TRUE;
  1241. X            if (ops[$4].ival != OSTR + (1<<8)) do_fancy_opens = TRUE; }
  1242. X    | PRINTF expr_list
  1243. X        { $$ = oper1(OPRINTF,$2);
  1244. X            if (!$2) need_entire = TRUE;
  1245. X        }
  1246. X    | BREAK
  1247. X        { $$ = oper0(OBREAK); }
  1248. X    | NEXT
  1249. X        { $$ = oper0(ONEXT); }
  1250. X    | EXIT
  1251. X        { $$ = oper0(OEXIT); }
  1252. X    | EXIT expr
  1253. X        { $$ = oper1(OEXIT,$2); }
  1254. X    | CONTINUE
  1255. X        { $$ = oper0(OCONTINUE); }
  1256. X    | RET
  1257. X        { $$ = oper0(ORETURN); }
  1258. X    | RET expr
  1259. X        { $$ = oper1(ORETURN,$2); }
  1260. X    | DELETE VAR '[' expr ']'
  1261. X        { $$ = oper2(ODELETE,aryrefarg($2),$4); }
  1262. X    ;
  1263. X
  1264. Xredir    : '>'    %prec FIELD
  1265. X        { $$ = oper1(OREDIR,$1); }
  1266. X    | GRGR
  1267. X        { $$ = oper1(OREDIR,string(">>",2)); }
  1268. X    | '|'
  1269. X        { $$ = oper1(OREDIR,string("|",1)); }
  1270. X    ;
  1271. X
  1272. Xcompound
  1273. X    : IF '(' cond ')' maybe statement
  1274. X        { $$ = oper2(OIF,$3,bl($6,$5)); }
  1275. X    | IF '(' cond ')' maybe statement ELSE maybe statement
  1276. X        { $$ = oper3(OIF,$3,bl($6,$5),bl($9,$8)); }
  1277. X    | WHILE '(' cond ')' maybe statement
  1278. X        { $$ = oper2(OWHILE,$3,bl($6,$5)); }
  1279. X    | DO maybe statement WHILE '(' cond ')'
  1280. X        { $$ = oper2(ODO,bl($3,$2),$6); }
  1281. X    | FOR '(' simpnull ';' cond ';' simpnull ')' maybe statement
  1282. X        { $$ = oper4(OFOR,$3,$5,$7,bl($10,$9)); }
  1283. X    | FOR '(' simpnull ';'  ';' simpnull ')' maybe statement
  1284. X        { $$ = oper4(OFOR,$3,string("",0),$6,bl($9,$8)); }
  1285. X    | FOR '(' expr ')' maybe statement
  1286. X        { $$ = oper2(OFORIN,$3,bl($6,$5)); }
  1287. X    | '{' maybe states '}' maybe
  1288. X        { $$ = oper3(OBLOCK,oper2(OJUNK,$2,$3),Nullop,$5); }
  1289. X    ;
  1290. X
  1291. X%%
  1292. X#include "a2py.c"
  1293. !STUFFY!FUNK!
  1294. echo Extracting Makefile.SH
  1295. sed >Makefile.SH <<'!STUFFY!FUNK!' -e 's/X//'
  1296. Xcase $CONFIG in
  1297. X'')
  1298. X    if test ! -f config.sh; then
  1299. X    ln ../config.sh . || \
  1300. X    ln ../../config.sh . || \
  1301. X    ln ../../../config.sh . || \
  1302. X    (echo "Can't find config.sh."; exit 1)
  1303. X    fi
  1304. X    . ./config.sh
  1305. X    ;;
  1306. Xesac
  1307. Xcase "$0" in
  1308. X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
  1309. Xesac
  1310. X
  1311. Xcase "$d_symlink" in
  1312. X*define*) sln='ln -s' ;;
  1313. X*) sln='ln';;
  1314. Xesac
  1315. X
  1316. Xcase "$d_dosuid" in
  1317. X*define*) suidperl='suidperl' ;;
  1318. X*) suidperl='';;
  1319. Xesac
  1320. X
  1321. Xecho "Extracting Makefile (with variable substitutions)"
  1322. Xcat >Makefile <<!GROK!THIS!
  1323. X# $Header: Makefile.SH,v 3.0 89/10/18 15:06:43 lwall Locked $
  1324. X#
  1325. X# $Log:    Makefile.SH,v $
  1326. X# Revision 3.0  89/10/18  15:06:43  lwall
  1327. X# 3.0 baseline
  1328. X# 
  1329. X
  1330. XCC = $cc
  1331. Xbin = $bin
  1332. Xprivlib = $privlib
  1333. Xmansrc = $mansrc
  1334. Xmanext = $manext
  1335. XCFLAGS = $ccflags $optimize $sockethdr
  1336. XLDFLAGS = $ldflags
  1337. XSMALL = $small
  1338. XLARGE = $large $split
  1339. Xmallocsrc = $mallocsrc
  1340. Xmallocobj = $mallocobj
  1341. XSLN = $sln
  1342. X
  1343. Xlibs = $libnm -lm $libdbm $libs $libndir $socketlib
  1344. X
  1345. Xpublic = perl taintperl $suidperl
  1346. X
  1347. X!GROK!THIS!
  1348. X
  1349. Xcat >>Makefile <<'!NO!SUBS!'
  1350. Xprivate = 
  1351. X
  1352. XMAKE = make
  1353. X
  1354. Xmanpages = perl.man
  1355. X
  1356. Xutil =
  1357. X
  1358. Xsh = Makefile.SH makedepend.SH
  1359. X
  1360. Xh1 = EXTERN.h INTERN.h arg.h array.h cmd.h config.h form.h handy.h
  1361. Xh2 = hash.h perl.h regcomp.h regexp.h spat.h stab.h str.h util.h
  1362. X
  1363. Xh = $(h1) $(h2)
  1364. X
  1365. Xc1 = array.c cmd.c cons.c consarg.c doarg.c doio.c dolist.c dump.c
  1366. Xc2 = eval.c form.c hash.c $(mallocsrc) perly.c regcomp.c regexec.c
  1367. Xc3 = stab.c str.c toke.c util.c
  1368. X
  1369. Xc = $(c1) $(c2) $(c3)
  1370. X
  1371. Xobj1 = array.o cmd.o cons.o consarg.o doarg.o doio.o dolist.o dump.o
  1372. Xobj2 = eval.o form.o hash.o $(mallocobj) perly.o regcomp.o regexec.o
  1373. Xobj3 = stab.o str.o toke.o util.o
  1374. X
  1375. Xobj = $(obj1) $(obj2) $(obj3)
  1376. X
  1377. Xtobj1 = tarray.o tcmd.o tcons.o tconsarg.o tdoarg.o tdoio.o tdolist.o tdump.o
  1378. Xtobj2 = teval.o tform.o thash.o $(mallocobj) tregcomp.o tregexec.o
  1379. Xtobj3 = tstab.o tstr.o ttoke.o tutil.o
  1380. X
  1381. Xtobj = $(tobj1) $(tobj2) $(tobj3)
  1382. X
  1383. Xlintflags = -hbvxac
  1384. X
  1385. Xaddedbyconf = Makefile.old bsd eunice filexp loc pdp11 usg v7
  1386. X
  1387. X# grrr
  1388. XSHELL = /bin/sh
  1389. X
  1390. X.c.o:
  1391. X    $(CC) -c $(CFLAGS) $(LARGE) $*.c
  1392. X
  1393. Xall: $(public) $(private) $(util) perl.man x2p/all
  1394. X    touch all
  1395. X
  1396. Xx2p/all:
  1397. X    cd x2p; $(MAKE) all
  1398. X
  1399. X# This is the standard version that contains no "taint" checks and is
  1400. X# used for all scripts that aren't set-id or running under something set-id.
  1401. X
  1402. Xperl: perl.o $(obj)
  1403. X    $(CC) $(LARGE) $(LDFLAGS) $(obj) perl.o $(libs) -o perl
  1404. X
  1405. X# This version, if specified in Configure, does ONLY those scripts which need
  1406. X# set-id emulation.  Suidperl must be setuid root.  It contains the "taint"
  1407. X# checks as well as the special code to validate that the script in question
  1408. X# has been invoked correctly.
  1409. X
  1410. Xsuidperl: tperl.o sperly.o $(tobj)
  1411. X    $(CC) $(LARGE) $(LDFLAGS) sperly.o $(tobj) tperl.o $(libs) -o suidperl
  1412. X
  1413. X# This version interprets scripts that are already set-id either via a wrapper
  1414. X# or through the kernel allowing set-id scripts (bad idea).  Taintperl must
  1415. X# NOT be setuid to root or anything else.  The only difference between it
  1416. X# and normal perl is the presence of the "taint" checks.
  1417. X
  1418. Xtaintperl: tperl.o tperly.o $(tobj)
  1419. X    $(CC) $(LARGE) $(LDFLAGS) tperly.o $(tobj) tperl.o $(libs) -o taintperl
  1420. X
  1421. X# Replicating all this junk is yucky, but I don't see a portable way to fix it.
  1422. X
  1423. Xtperl.o: perl.c perly.h perl.h EXTERN.h regexp.h util.h INTERN.h handy.h \
  1424. X    config.h stab.h
  1425. X    /bin/rm -f tperl.c
  1426. X    $(SLN) perl.c tperl.c
  1427. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tperl.c
  1428. X    /bin/rm -f tperl.c
  1429. X
  1430. Xtperly.o: perly.c
  1431. X    /bin/rm -f tperly.c
  1432. X    $(SLN) perly.c tperly.c
  1433. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tperly.c
  1434. X    /bin/rm -f tperly.c
  1435. X
  1436. Xsperly.o: perly.c perl.h handy.h perly.h patchlevel.h
  1437. X    /bin/rm -f sperly.c
  1438. X    $(SLN) perly.c sperly.c
  1439. X    $(CC) -c -DTAINT -DIAMSUID $(CFLAGS) $(LARGE) sperly.c
  1440. X    /bin/rm -f sperly.c
  1441. X
  1442. Xtarray.o: array.c
  1443. X    /bin/rm -f tarray.c
  1444. X    $(SLN) array.c tarray.c
  1445. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tarray.c
  1446. X    /bin/rm -f tarray.c
  1447. X
  1448. Xtcmd.o: cmd.c
  1449. X    /bin/rm -f tcmd.c
  1450. X    $(SLN) cmd.c tcmd.c
  1451. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tcmd.c
  1452. X    /bin/rm -f tcmd.c
  1453. X
  1454. Xtcons.o: cons.c
  1455. X    /bin/rm -f tcons.c
  1456. X    $(SLN) cons.c tcons.c
  1457. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tcons.c
  1458. X    /bin/rm -f tcons.c
  1459. X
  1460. Xtconsarg.o: consarg.c
  1461. X    /bin/rm -f tconsarg.c
  1462. X    $(SLN) consarg.c tconsarg.c
  1463. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tconsarg.c
  1464. X    /bin/rm -f tconsarg.c
  1465. X
  1466. Xtdoarg.o: doarg.c
  1467. X    /bin/rm -f tdoarg.c
  1468. X    $(SLN) doarg.c tdoarg.c
  1469. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tdoarg.c
  1470. X    /bin/rm -f tdoarg.c
  1471. X
  1472. Xtdoio.o: doio.c
  1473. X    /bin/rm -f tdoio.c
  1474. X    $(SLN) doio.c tdoio.c
  1475. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tdoio.c
  1476. X    /bin/rm -f tdoio.c
  1477. X
  1478. Xtdolist.o: dolist.c
  1479. X    /bin/rm -f tdolist.c
  1480. X    $(SLN) dolist.c tdolist.c
  1481. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tdolist.c
  1482. X    /bin/rm -f tdolist.c
  1483. X
  1484. Xtdump.o: dump.c
  1485. X    /bin/rm -f tdump.c
  1486. X    $(SLN) dump.c tdump.c
  1487. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tdump.c
  1488. X    /bin/rm -f tdump.c
  1489. X
  1490. Xteval.o: eval.c
  1491. X    /bin/rm -f teval.c
  1492. X    $(SLN) eval.c teval.c
  1493. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) teval.c
  1494. X    /bin/rm -f teval.c
  1495. X
  1496. Xtform.o: form.c
  1497. X    /bin/rm -f tform.c
  1498. X    $(SLN) form.c tform.c
  1499. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tform.c
  1500. X    /bin/rm -f tform.c
  1501. X
  1502. Xthash.o: hash.c
  1503. X    /bin/rm -f thash.c
  1504. X    $(SLN) hash.c thash.c
  1505. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) thash.c
  1506. X    /bin/rm -f thash.c
  1507. X
  1508. Xtregcomp.o: regcomp.c
  1509. X    /bin/rm -f tregcomp.c
  1510. X    $(SLN) regcomp.c tregcomp.c
  1511. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tregcomp.c
  1512. X    /bin/rm -f tregcomp.c
  1513. X
  1514. Xtregexec.o: regexec.c
  1515. X    /bin/rm -f tregexec.c
  1516. X    $(SLN) regexec.c tregexec.c
  1517. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tregexec.c
  1518. X    /bin/rm -f tregexec.c
  1519. X
  1520. Xtstab.o: stab.c
  1521. X    /bin/rm -f tstab.c
  1522. X    $(SLN) stab.c tstab.c
  1523. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tstab.c
  1524. X    /bin/rm -f tstab.c
  1525. X
  1526. Xtstr.o: str.c
  1527. X    /bin/rm -f tstr.c
  1528. X    $(SLN) str.c tstr.c
  1529. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tstr.c
  1530. X    /bin/rm -f tstr.c
  1531. X
  1532. Xttoke.o: toke.c
  1533. X    /bin/rm -f ttoke.c
  1534. X    $(SLN) toke.c ttoke.c
  1535. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) ttoke.c
  1536. X    /bin/rm -f ttoke.c
  1537. X
  1538. Xtutil.o: util.c
  1539. X    /bin/rm -f tutil.c
  1540. X    $(SLN) util.c tutil.c
  1541. X    $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tutil.c
  1542. X    /bin/rm -f tutil.c
  1543. X
  1544. Xperl.c perly.h: perl.y
  1545. X    @ echo Expect 25 shift/reduce errors...
  1546. X    yacc -d perl.y
  1547. X    mv y.tab.c perl.c
  1548. X    mv y.tab.h perly.h
  1549. X
  1550. Xperl.o: perl.c perly.h perl.h EXTERN.h regexp.h util.h INTERN.h handy.h \
  1551. X    config.h arg.h stab.h
  1552. X    $(CC) -c $(CFLAGS) $(LARGE) perl.c
  1553. X
  1554. Xperl.man: perl.man.1 perl.man.2 perl.man.3 perl.man.4 patchlevel.h perl
  1555. X    ./perl  -e '($$r,$$p)=$$]=~/(\d+\.\d+).*\n\D*(\d+)/;' \
  1556. X        -e 'print ".ds RP Release $$r Patchlevel $$p\n";' >perl.man
  1557. X    cat perl.man.[1-4] >>perl.man
  1558. X
  1559. Xinstall: all
  1560. X# won't work with csh
  1561. X    export PATH || exit 1
  1562. X    - rm -f $(bin)/perl.old $(bin)/suidperl $(bin)/taintperl
  1563. X    - mv $(bin)/perl $(bin)/perl.old 2>/dev/null
  1564. X    - if test `pwd` != $(bin); then cp $(public) $(bin); fi
  1565. X    - cd $(bin); \
  1566. Xfor pub in $(public); do \
  1567. Xchmod +x `basename $$pub`; \
  1568. Xdone
  1569. X    - chmod 755 $(bin)/taintperl 2>/dev/null
  1570. X!NO!SUBS!
  1571. X
  1572. Xcase "$d_dosuid" in
  1573. X*define*)
  1574. X    cat >>Makefile <<'!NO!SUBS!'
  1575. X    - chmod 4711 $(bin)/suidperl 2>/dev/null
  1576. X!NO!SUBS!
  1577. X    ;;
  1578. Xesac
  1579. X
  1580. Xcat >>Makefile <<'!NO!SUBS!'
  1581. X    - test $(bin) = /usr/bin || rm -f /usr/bin/perl
  1582. X    - test $(bin) = /usr/bin || $(SLN) $(bin)/perl /usr/bin || cp $(bin)/perl /usr/bin
  1583. X    - sh ./makedir $(privlib)
  1584. X    - \
  1585. Xif test `pwd` != $(privlib); then \
  1586. Xcp $(private) lib/*.pl $(privlib); \
  1587. Xfi
  1588. X#    cd $(privlib); \
  1589. X#for priv in $(private); do \
  1590. X#chmod +x `basename $$priv`; \
  1591. X#done
  1592. X    - if test `pwd` != $(mansrc); then \
  1593. Xfor page in $(manpages); do \
  1594. Xcp $$page $(mansrc)/`basename $$page .man`.$(manext); \
  1595. Xdone; \
  1596. Xfi
  1597. X    cd x2p; $(MAKE) install
  1598. X
  1599. Xclean:
  1600. X    rm -f *.o all perl taintperl perl.man
  1601. X    cd x2p; $(MAKE) clean
  1602. X
  1603. Xrealclean:
  1604. X    cd x2p; $(MAKE) realclean
  1605. X    rm -f perl *.orig */*.orig *~ */*~ *.o core $(addedbyconf) perl.man
  1606. X    rm -f perl.c perly.h t/perl Makefile config.h makedepend makedir
  1607. X    rm -f x2p/Makefile
  1608. X
  1609. X# The following lint has practically everything turned on.  Unfortunately,
  1610. X# you have to wade through a lot of mumbo jumbo that can't be suppressed.
  1611. X# If the source file has a /*NOSTRICT*/ somewhere, ignore the lint message
  1612. X# for that spot.
  1613. X
  1614. Xlint: perl.c $(c)
  1615. X    lint $(lintflags) $(defs) perl.c $(c) > perl.fuzz
  1616. X
  1617. Xdepend: makedepend
  1618. X    - test -f perly.h || cp /dev/null perly.h
  1619. X    ./makedepend
  1620. X    - test -s perly.h || /bin/rm -f perly.h
  1621. X    cd x2p; $(MAKE) depend
  1622. X
  1623. Xtest: perl
  1624. X    - chmod +x t/TEST t/base.* t/comp.* t/cmd.* t/io.* t/op.*; \
  1625. X    cd t && (rm -f perl; $(SLN) ../perl .) && ./perl TEST
  1626. X
  1627. Xclist:
  1628. X    echo $(c) | tr ' ' '\012' >.clist
  1629. X
  1630. Xhlist:
  1631. X    echo $(h) | tr ' ' '\012' >.hlist
  1632. X
  1633. Xshlist:
  1634. X    echo $(sh) | tr ' ' '\012' >.shlist
  1635. X
  1636. X# AUTOMATICALLY GENERATED MAKE DEPENDENCIES--PUT NOTHING BELOW THIS LINE
  1637. Xperly.o $(obj):
  1638. X    @ echo "You haven't done a "'"make depend" yet!'; exit 1
  1639. Xmakedepend: makedepend.SH
  1640. X    /bin/sh makedepend.SH
  1641. X!NO!SUBS!
  1642. X$eunicefix Makefile
  1643. Xcase `pwd` in
  1644. X*SH)
  1645. X    $rm -f ../Makefile
  1646. X    ln Makefile ../Makefile
  1647. X    ;;
  1648. Xesac
  1649. !STUFFY!FUNK!
  1650. echo Extracting evalargs.xc
  1651. sed >evalargs.xc <<'!STUFFY!FUNK!' -e 's/X//'
  1652. X/* This file is included by eval.c.  It's separate from eval.c to keep
  1653. X * kit sizes from getting too big.
  1654. X */
  1655. X
  1656. X/* $Header: evalargs.xc,v 3.0 89/10/18 15:17:16 lwall Locked $
  1657. X *
  1658. X * $Log:    evalargs.xc,v $
  1659. X * Revision 3.0  89/10/18  15:17:16  lwall
  1660. X * 3.0 baseline
  1661. X * 
  1662. X */
  1663. X
  1664. X    for (anum = 1; anum <= maxarg; anum++) {
  1665. X    argflags = arg[anum].arg_flags;
  1666. X    argtype = arg[anum].arg_type;
  1667. X    argptr = arg[anum].arg_ptr;
  1668. X      re_eval:
  1669. X    switch (argtype) {
  1670. X    default:
  1671. X        st[++sp] = &str_undef;
  1672. X#ifdef DEBUGGING
  1673. X        tmps = "NULL";
  1674. X#endif
  1675. X        break;
  1676. X    case A_EXPR:
  1677. X#ifdef DEBUGGING
  1678. X        if (debug & 8) {
  1679. X        tmps = "EXPR";
  1680. X        deb("%d.EXPR =>\n",anum);
  1681. X        }
  1682. X#endif
  1683. X        sp = eval(argptr.arg_arg,
  1684. X        (argflags & AF_ARYOK) ? G_ARRAY : G_SCALAR, sp);
  1685. X        if (sp + (maxarg - anum) > stack->ary_max)
  1686. X        astore(stack, sp + (maxarg - anum), Nullstr);
  1687. X        st = stack->ary_array;    /* possibly reallocated */
  1688. X        break;
  1689. X    case A_CMD:
  1690. X#ifdef DEBUGGING
  1691. X        if (debug & 8) {
  1692. X        tmps = "CMD";
  1693. X        deb("%d.CMD (%lx) =>\n",anum,argptr.arg_cmd);
  1694. X        }
  1695. X#endif
  1696. X        sp = cmd_exec(argptr.arg_cmd, gimme, sp);
  1697. X        if (sp + (maxarg - anum) > stack->ary_max)
  1698. X        astore(stack, sp + (maxarg - anum), Nullstr);
  1699. X        st = stack->ary_array;    /* possibly reallocated */
  1700. X        break;
  1701. X    case A_LARYSTAB:
  1702. X        ++sp;
  1703. X        str = afetch(stab_array(argptr.arg_stab),
  1704. X        arg[anum].arg_len - arybase, TRUE);
  1705. X#ifdef DEBUGGING
  1706. X        if (debug & 8) {
  1707. X        (void)sprintf(buf,"LARYSTAB $%s[%d]",stab_name(argptr.arg_stab),
  1708. X            arg[anum].arg_len);
  1709. X        tmps = buf;
  1710. X        }
  1711. X#endif
  1712. X        goto do_crement;
  1713. X    case A_ARYSTAB:
  1714. X        st[++sp] = afetch(stab_array(argptr.arg_stab),
  1715. X        arg[anum].arg_len - arybase, FALSE);
  1716. X        if (!st[sp])
  1717. X        st[sp] = &str_undef;
  1718. X#ifdef DEBUGGING
  1719. X        if (debug & 8) {
  1720. X        (void)sprintf(buf,"ARYSTAB $%s[%d]",stab_name(argptr.arg_stab),
  1721. X            arg[anum].arg_len);
  1722. X        tmps = buf;
  1723. X        }
  1724. X#endif
  1725. X        break;
  1726. X    case A_STAR:
  1727. X        st[++sp] = (STR*)argptr.arg_stab;
  1728. X#ifdef DEBUGGING
  1729. X        if (debug & 8) {
  1730. X        (void)sprintf(buf,"STAR *%s",stab_name(argptr.arg_stab));
  1731. X        tmps = buf;
  1732. X        }
  1733. X#endif
  1734. X        break;
  1735. X    case A_LSTAR:
  1736. X        str = st[++sp] = (STR*)argptr.arg_stab;
  1737. X#ifdef DEBUGGING
  1738. X        if (debug & 8) {
  1739. X        (void)sprintf(buf,"LSTAR *%s",stab_name(argptr.arg_stab));
  1740. X        tmps = buf;
  1741. X        }
  1742. X#endif
  1743. X        break;
  1744. X    case A_STAB:
  1745. X        st[++sp] = STAB_STR(argptr.arg_stab);
  1746. X#ifdef DEBUGGING
  1747. X        if (debug & 8) {
  1748. X        (void)sprintf(buf,"STAB $%s",stab_name(argptr.arg_stab));
  1749. X        tmps = buf;
  1750. X        }
  1751. X#endif
  1752. X        break;
  1753. X    case A_LEXPR:
  1754. X#ifdef DEBUGGING
  1755. X        if (debug & 8) {
  1756. X        tmps = "LEXPR";
  1757. X        deb("%d.LEXPR =>\n",anum);
  1758. X        }
  1759. X#endif
  1760. X        if (argflags & AF_ARYOK) {
  1761. X        sp = eval(argptr.arg_arg, G_ARRAY, sp);
  1762. X        if (sp + (maxarg - anum) > stack->ary_max)
  1763. X            astore(stack, sp + (maxarg - anum), Nullstr);
  1764. X        st = stack->ary_array;    /* possibly reallocated */
  1765. X        }
  1766. X        else {
  1767. X        sp = eval(argptr.arg_arg, G_SCALAR, sp);
  1768. X        st = stack->ary_array;    /* possibly reallocated */
  1769. X        str = st[sp];
  1770. X        goto do_crement;
  1771. X        }
  1772. X        break;
  1773. X    case A_LVAL:
  1774. X#ifdef DEBUGGING
  1775. X        if (debug & 8) {
  1776. X        (void)sprintf(buf,"LVAL $%s",stab_name(argptr.arg_stab));
  1777. X        tmps = buf;
  1778. X        }
  1779. X#endif
  1780. X        ++sp;
  1781. X        str = STAB_STR(argptr.arg_stab);
  1782. X        if (!str)
  1783. X        fatal("panic: A_LVAL");
  1784. X      do_crement:
  1785. X        assigning = TRUE;
  1786. X        if (argflags & AF_PRE) {
  1787. X        if (argflags & AF_UP)
  1788. X            str_inc(str);
  1789. X        else
  1790. X            str_dec(str);
  1791. X        STABSET(str);
  1792. X        st[sp] = str;
  1793. X        str = arg->arg_ptr.arg_str;
  1794. X        }
  1795. X        else if (argflags & AF_POST) {
  1796. X        st[sp] = str_static(str);
  1797. X        if (argflags & AF_UP)
  1798. X            str_inc(str);
  1799. X        else
  1800. X            str_dec(str);
  1801. X        STABSET(str);
  1802. X        str = arg->arg_ptr.arg_str;
  1803. X        }
  1804. X        else
  1805. X        st[sp] = str;
  1806. X        break;
  1807. X    case A_LARYLEN:
  1808. X        ++sp;
  1809. X        stab = argptr.arg_stab;
  1810. X        str = stab_array(argptr.arg_stab)->ary_magic;
  1811. X        if (argflags & (AF_PRE|AF_POST))
  1812. X        str_numset(str,(double)(stab_array(stab)->ary_fill+arybase));
  1813. X#ifdef DEBUGGING
  1814. X        tmps = "LARYLEN";
  1815. X#endif
  1816. X        if (!str)
  1817. X        fatal("panic: A_LEXPR");
  1818. X        goto do_crement;
  1819. X    case A_ARYLEN:
  1820. X        stab = argptr.arg_stab;
  1821. X        st[++sp] = stab_array(stab)->ary_magic;
  1822. X        str_numset(st[sp],(double)(stab_array(stab)->ary_fill+arybase));
  1823. X#ifdef DEBUGGING
  1824. X        tmps = "ARYLEN";
  1825. X#endif
  1826. X        break;
  1827. X    case A_SINGLE:
  1828. X        st[++sp] = argptr.arg_str;
  1829. X#ifdef DEBUGGING
  1830. X        tmps = "SINGLE";
  1831. X#endif
  1832. X        break;
  1833. X    case A_DOUBLE:
  1834. X        (void) interp(str,argptr.arg_str,sp);
  1835. X        st = stack->ary_array;
  1836. X        st[++sp] = str;
  1837. X#ifdef DEBUGGING
  1838. X        tmps = "DOUBLE";
  1839. X#endif
  1840. X        break;
  1841. X    case A_BACKTICK:
  1842. X        tmps = str_get(interp(str,argptr.arg_str,sp));
  1843. X        st = stack->ary_array;
  1844. X#ifdef TAINT
  1845. X        taintproper("Insecure dependency in ``");
  1846. X#endif
  1847. X        fp = mypopen(tmps,"r");
  1848. X        str_set(str,"");
  1849. X        if (fp) {
  1850. X        while (str_gets(str,fp,str->str_cur) != Nullch)
  1851. X            ;
  1852. X        statusvalue = mypclose(fp);
  1853. X        }
  1854. X        else
  1855. X        statusvalue = -1;
  1856. X
  1857. X        st[++sp] = str;
  1858. X#ifdef DEBUGGING
  1859. X        tmps = "BACK";
  1860. X#endif
  1861. X        break;
  1862. X    case A_WANTARRAY:
  1863. X        {
  1864. X        extern int wantarray;
  1865. X
  1866. X        if (wantarray == G_ARRAY)
  1867. X            st[++sp] = &str_yes;
  1868. X        else
  1869. X            st[++sp] = &str_no;
  1870. X        }
  1871. X#ifdef DEBUGGING
  1872. X        tmps = "WANTARRAY";
  1873. X#endif
  1874. X        break;
  1875. X    case A_INDREAD:
  1876. X        last_in_stab = stabent(str_get(STAB_STR(argptr.arg_stab)),TRUE);
  1877. X        old_record_separator = record_separator;
  1878. X        goto do_read;
  1879. X    case A_GLOB:
  1880. X        argflags |= AF_POST;    /* enable newline chopping */
  1881. X        last_in_stab = argptr.arg_stab;
  1882. X        old_record_separator = record_separator;
  1883. X        if (csh > 0)
  1884. X        record_separator = 0;
  1885. X        else
  1886. X        record_separator = '\n';
  1887. X        goto do_read;
  1888. X    case A_READ:
  1889. X        last_in_stab = argptr.arg_stab;
  1890. X        old_record_separator = record_separator;
  1891. X      do_read:
  1892. X        if (anum > 1)        /* assign to scalar */
  1893. X        gimme = G_SCALAR;    /* force context to scalar */
  1894. X        ++sp;
  1895. X        fp = Nullfp;
  1896. X        if (stab_io(last_in_stab)) {
  1897. X        fp = stab_io(last_in_stab)->ifp;
  1898. X        if (!fp) {
  1899. X            if (stab_io(last_in_stab)->flags & IOF_ARGV) {
  1900. X            if (stab_io(last_in_stab)->flags & IOF_START) {
  1901. X                stab_io(last_in_stab)->flags &= ~IOF_START;
  1902. X                stab_io(last_in_stab)->lines = 0;
  1903. X                if (alen(stab_array(last_in_stab)) < 0) {
  1904. X                tmpstr = str_make("-",1); /* assume stdin */
  1905. X                (void)apush(stab_array(last_in_stab), tmpstr);
  1906. X                }
  1907. X            }
  1908. X            fp = nextargv(last_in_stab);
  1909. X            if (!fp)  /* Note: fp != stab_io(last_in_stab)->ifp */
  1910. X                (void)do_close(last_in_stab,FALSE); /* now it does*/
  1911. X            }
  1912. X            else if (argtype == A_GLOB) {
  1913. X            (void) interp(str,stab_val(last_in_stab),sp);
  1914. X            st = stack->ary_array;
  1915. X            tmpstr = Str_new(55,0);
  1916. X            if (csh > 0) {
  1917. X                str_set(tmpstr,"/bin/csh -cf 'set nonomatch; glob ");
  1918. X                str_scat(tmpstr,str);
  1919. X                str_cat(tmpstr,"'|");
  1920. X            }
  1921. X            else {
  1922. X                str_set(tmpstr, "echo ");
  1923. X                str_scat(tmpstr,str);
  1924. X                str_cat(tmpstr,
  1925. X                  "|tr -s ' \t\f\r' '\\012\\012\\012\\012'|");
  1926. X            }
  1927. X            (void)do_open(last_in_stab,tmpstr->str_ptr);
  1928. X            fp = stab_io(last_in_stab)->ifp;
  1929. X            }
  1930. X        }
  1931. X        }
  1932. X        if (!fp && dowarn)
  1933. X        warn("Read on closed filehandle <%s>",stab_name(last_in_stab));
  1934. X      keepgoing:
  1935. X        if (!fp)
  1936. X        st[sp] = &str_undef;
  1937. X        else if (!str_gets(str,fp, optype == O_RCAT ? str->str_cur : 0)) {
  1938. X        clearerr(fp);
  1939. X        if (stab_io(last_in_stab)->flags & IOF_ARGV) {
  1940. X            fp = nextargv(last_in_stab);
  1941. X            if (fp)
  1942. X            goto keepgoing;
  1943. X            (void)do_close(last_in_stab,FALSE);
  1944. X            stab_io(last_in_stab)->flags |= IOF_START;
  1945. X        }
  1946. X        else if (argflags & AF_POST) {
  1947. X            (void)do_close(last_in_stab,FALSE);
  1948. X        }
  1949. X        st[sp] = &str_undef;
  1950. X        record_separator = old_record_separator;
  1951. X        if (gimme == G_ARRAY) {
  1952. X            --sp;
  1953. X            goto array_return;
  1954. X        }
  1955. X        break;
  1956. X        }
  1957. X        else {
  1958. X        stab_io(last_in_stab)->lines++;
  1959. X        st[sp] = str;
  1960. X#ifdef TAINT
  1961. X        str->str_tainted = 1; /* Anything from the outside world...*/
  1962. X#endif
  1963. X        if (argflags & AF_POST) {
  1964. X            if (str->str_cur > 0)
  1965. X            str->str_cur--;
  1966. X            if (str->str_ptr[str->str_cur] == record_separator)
  1967. X            str->str_ptr[str->str_cur] = '\0';
  1968. X            else
  1969. X            str->str_cur++;
  1970. X            for (tmps = str->str_ptr; *tmps; tmps++)
  1971. X            if (!isalpha(*tmps) && !isdigit(*tmps) &&
  1972. X                index("$&*(){}[]'\";\\|?<>~`",*tmps))
  1973. X                break;
  1974. X            if (*tmps && stat(str->str_ptr,&statbuf) < 0)
  1975. X            goto keepgoing;        /* unmatched wildcard? */
  1976. X        }
  1977. X        if (gimme == G_ARRAY) {
  1978. X            st[sp] = str_static(st[sp]);
  1979. X            if (++sp > stack->ary_max) {
  1980. X            astore(stack, sp, Nullstr);
  1981. X            st = stack->ary_array;
  1982. X            }
  1983. X            goto keepgoing;
  1984. X        }
  1985. X        }
  1986. X        record_separator = old_record_separator;
  1987. X#ifdef DEBUGGING
  1988. X        tmps = "READ";
  1989. X#endif
  1990. X        break;
  1991. X    }
  1992. X#ifdef DEBUGGING
  1993. X    if (debug & 8)
  1994. X        deb("%d.%s = '%s'\n",anum,tmps,str_peek(st[sp]));
  1995. X#endif
  1996. X    if (anum < 8)
  1997. X        arglast[anum] = sp;
  1998. X    }
  1999. !STUFFY!FUNK!
  2000. echo ""
  2001. echo "End of kit 19 (of 24)"
  2002. cat /dev/null >kit19isdone
  2003. run=''
  2004. config=''
  2005. 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
  2006.     if test -f kit${iskit}isdone; then
  2007.     run="$run $iskit"
  2008.     else
  2009.     todo="$todo $iskit"
  2010.     fi
  2011. done
  2012. case $todo in
  2013.     '')
  2014.     echo "You have run all your kits.  Please read README and then type Configure."
  2015.     chmod 755 Configure
  2016.     ;;
  2017.     *)  echo "You have run$run."
  2018.     echo "You still need to run$todo."
  2019.     ;;
  2020. esac
  2021. : Someone might mail this, so...
  2022. exit
  2023.  
  2024. -- 
  2025. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  2026. Use a domain-based address or give alternate paths, or you may lose out.
  2027.