v15i100: Perl, version 2, Part11/15
Rich Salz
rsalz at bbn.com
Wed Jul 13 14:17:12 AEST 1988
Submitted-by: Larry Wall <lwall at jpl-devvax.jpl.nasa.gov>
Posting-number: Volume 15, Issue 100
Archive-name: perl2/part11
#! /bin/sh
# Make a new directory for the perl sources, cd to it, and run kits 1
# thru 15 through sh. When all 15 kits have been run, read README.
echo "This is perl 2.0 kit 11 (of 15). If kit 11 is complete, the line"
echo '"'"End of kit 11 (of 15)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
mkdir t x2p 2>/dev/null
echo Extracting x2p/str.c
sed >x2p/str.c <<'!STUFFY!FUNK!' -e 's/X//'
X/* $Header: str.c,v 2.0 88/06/05 00:16:02 root Exp $
X *
X * $Log: str.c,v $
X * Revision 2.0 88/06/05 00:16:02 root
X * Baseline version 2.0.
X *
X */
X
X#include "handy.h"
X#include "EXTERN.h"
X#include "util.h"
X#include "a2p.h"
X
Xstr_numset(str,num)
Xregister STR *str;
Xdouble num;
X{
X str->str_nval = num;
X str->str_pok = 0; /* invalidate pointer */
X str->str_nok = 1; /* validate number */
X}
X
Xchar *
Xstr_2ptr(str)
Xregister STR *str;
X{
X register char *s;
X
X if (!str)
X return "";
X GROWSTR(&(str->str_ptr), &(str->str_len), 24);
X s = str->str_ptr;
X if (str->str_nok) {
X sprintf(s,"%.20g",str->str_nval);
X while (*s) s++;
X }
X *s = '\0';
X str->str_cur = s - str->str_ptr;
X str->str_pok = 1;
X#ifdef DEBUGGING
X if (debug & 32)
X fprintf(stderr,"0x%lx ptr(%s)\n",str,str->str_ptr);
X#endif
X return str->str_ptr;
X}
X
Xdouble
Xstr_2num(str)
Xregister STR *str;
X{
X if (!str)
X return 0.0;
X if (str->str_len && str->str_pok)
X str->str_nval = atof(str->str_ptr);
X else
X str->str_nval = 0.0;
X str->str_nok = 1;
X#ifdef DEBUGGING
X if (debug & 32)
X fprintf(stderr,"0x%lx num(%g)\n",str,str->str_nval);
X#endif
X return str->str_nval;
X}
X
Xstr_sset(dstr,sstr)
XSTR *dstr;
Xregister STR *sstr;
X{
X if (!sstr)
X str_nset(dstr,No,0);
X else if (sstr->str_nok)
X str_numset(dstr,sstr->str_nval);
X else if (sstr->str_pok)
X str_nset(dstr,sstr->str_ptr,sstr->str_cur);
X else
X str_nset(dstr,"",0);
X}
X
Xstr_nset(str,ptr,len)
Xregister STR *str;
Xregister char *ptr;
Xregister int len;
X{
X GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
X bcopy(ptr,str->str_ptr,len);
X str->str_cur = len;
X *(str->str_ptr+str->str_cur) = '\0';
X str->str_nok = 0; /* invalidate number */
X str->str_pok = 1; /* validate pointer */
X}
X
Xstr_set(str,ptr)
Xregister STR *str;
Xregister char *ptr;
X{
X register int len;
X
X if (!ptr)
X ptr = "";
X len = strlen(ptr);
X GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
X bcopy(ptr,str->str_ptr,len+1);
X str->str_cur = len;
X str->str_nok = 0; /* invalidate number */
X str->str_pok = 1; /* validate pointer */
X}
X
Xstr_chop(str,ptr) /* like set but assuming ptr is in str */
Xregister STR *str;
Xregister char *ptr;
X{
X if (!(str->str_pok))
X str_2ptr(str);
X str->str_cur -= (ptr - str->str_ptr);
X bcopy(ptr,str->str_ptr, str->str_cur + 1);
X str->str_nok = 0; /* invalidate number */
X str->str_pok = 1; /* validate pointer */
X}
X
Xstr_ncat(str,ptr,len)
Xregister STR *str;
Xregister char *ptr;
Xregister int len;
X{
X if (!(str->str_pok))
X str_2ptr(str);
X GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
X bcopy(ptr,str->str_ptr+str->str_cur,len);
X str->str_cur += len;
X *(str->str_ptr+str->str_cur) = '\0';
X str->str_nok = 0; /* invalidate number */
X str->str_pok = 1; /* validate pointer */
X}
X
Xstr_scat(dstr,sstr)
XSTR *dstr;
Xregister STR *sstr;
X{
X if (!(sstr->str_pok))
X str_2ptr(sstr);
X if (sstr)
X str_ncat(dstr,sstr->str_ptr,sstr->str_cur);
X}
X
Xstr_cat(str,ptr)
Xregister STR *str;
Xregister char *ptr;
X{
X register int len;
X
X if (!ptr)
X return;
X if (!(str->str_pok))
X str_2ptr(str);
X len = strlen(ptr);
X GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
X bcopy(ptr,str->str_ptr+str->str_cur,len+1);
X str->str_cur += len;
X str->str_nok = 0; /* invalidate number */
X str->str_pok = 1; /* validate pointer */
X}
X
Xchar *
Xstr_append_till(str,from,delim,keeplist)
Xregister STR *str;
Xregister char *from;
Xregister int delim;
Xchar *keeplist;
X{
X register char *to;
X register int len;
X
X if (!from)
X return Nullch;
X len = strlen(from);
X GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
X str->str_nok = 0; /* invalidate number */
X str->str_pok = 1; /* validate pointer */
X to = str->str_ptr+str->str_cur;
X for (; *from; from++,to++) {
X if (*from == '\\' && from[1] && delim != '\\') {
X if (!keeplist) {
X if (from[1] == delim || from[1] == '\\')
X from++;
X else
X *to++ = *from++;
X }
X else if (index(keeplist,from[1]))
X *to++ = *from++;
X else
X from++;
X }
X else if (*from == delim)
X break;
X *to = *from;
X }
X *to = '\0';
X str->str_cur = to - str->str_ptr;
X return from;
X}
X
XSTR *
Xstr_new(len)
Xint len;
X{
X register STR *str;
X
X if (freestrroot) {
X str = freestrroot;
X freestrroot = str->str_link.str_next;
X }
X else {
X str = (STR *) safemalloc(sizeof(STR));
X bzero((char*)str,sizeof(STR));
X }
X if (len)
X GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
X return str;
X}
X
Xvoid
Xstr_grow(str,len)
Xregister STR *str;
Xint len;
X{
X if (len && str)
X GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
X}
X
X/* make str point to what nstr did */
X
Xvoid
Xstr_replace(str,nstr)
Xregister STR *str;
Xregister STR *nstr;
X{
X safefree(str->str_ptr);
X str->str_ptr = nstr->str_ptr;
X str->str_len = nstr->str_len;
X str->str_cur = nstr->str_cur;
X str->str_pok = nstr->str_pok;
X if (str->str_nok = nstr->str_nok)
X str->str_nval = nstr->str_nval;
X safefree((char*)nstr);
X}
X
Xvoid
Xstr_free(str)
Xregister STR *str;
X{
X if (!str)
X return;
X if (str->str_len)
X str->str_ptr[0] = '\0';
X str->str_cur = 0;
X str->str_nok = 0;
X str->str_pok = 0;
X str->str_link.str_next = freestrroot;
X freestrroot = str;
X}
X
Xstr_len(str)
Xregister STR *str;
X{
X if (!str)
X return 0;
X if (!(str->str_pok))
X str_2ptr(str);
X if (str->str_len)
X return str->str_cur;
X else
X return 0;
X}
X
Xchar *
Xstr_gets(str,fp)
Xregister STR *str;
Xregister FILE *fp;
X{
X#ifdef STDSTDIO /* Here is some breathtakingly efficient cheating */
X
X register char *bp; /* we're going to steal some values */
X register int cnt; /* from the stdio struct and put EVERYTHING */
X register STDCHAR *ptr; /* in the innermost loop into registers */
X register char newline = '\n'; /* (assuming at least 6 registers) */
X int i;
X int bpx;
X
X cnt = fp->_cnt; /* get count into register */
X str->str_nok = 0; /* invalidate number */
X str->str_pok = 1; /* validate pointer */
X if (str->str_len <= cnt) /* make sure we have the room */
X GROWSTR(&(str->str_ptr), &(str->str_len), cnt+1);
X bp = str->str_ptr; /* move these two too to registers */
X ptr = fp->_ptr;
X for (;;) {
X while (--cnt >= 0) {
X if ((*bp++ = *ptr++) == newline)
X if (bp <= str->str_ptr || bp[-2] != '\\')
X goto thats_all_folks;
X else {
X line++;
X bp -= 2;
X }
X }
X
X fp->_cnt = cnt; /* deregisterize cnt and ptr */
X fp->_ptr = ptr;
X i = _filbuf(fp); /* get more characters */
X cnt = fp->_cnt;
X ptr = fp->_ptr; /* reregisterize cnt and ptr */
X
X bpx = bp - str->str_ptr; /* prepare for possible relocation */
X GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + cnt + 1);
X bp = str->str_ptr + bpx; /* reconstitute our pointer */
X
X if (i == newline) { /* all done for now? */
X *bp++ = i;
X goto thats_all_folks;
X }
X else if (i == EOF) /* all done for ever? */
X goto thats_all_folks;
X *bp++ = i; /* now go back to screaming loop */
X }
X
Xthats_all_folks:
X fp->_cnt = cnt; /* put these back or we're in trouble */
X fp->_ptr = ptr;
X *bp = '\0';
X str->str_cur = bp - str->str_ptr; /* set length */
X
X#else /* !STDSTDIO */ /* The big, slow, and stupid way */
X
X static char buf[4192];
X
X if (fgets(buf, sizeof buf, fp) != Nullch)
X str_set(str, buf);
X else
X str_set(str, No);
X
X#endif /* STDSTDIO */
X
X return str->str_cur ? str->str_ptr : Nullch;
X}
X
Xvoid
Xstr_inc(str)
Xregister STR *str;
X{
X register char *d;
X
X if (!str)
X return;
X if (str->str_nok) {
X str->str_nval += 1.0;
X str->str_pok = 0;
X return;
X }
X if (!str->str_pok) {
X str->str_nval = 1.0;
X str->str_nok = 1;
X return;
X }
X for (d = str->str_ptr; *d && *d != '.'; d++) ;
X d--;
X if (!isdigit(*str->str_ptr) || !isdigit(*d) ) {
X str_numset(str,atof(str->str_ptr) + 1.0); /* punt */
X return;
X }
X while (d >= str->str_ptr) {
X if (++*d <= '9')
X return;
X *(d--) = '0';
X }
X /* oh,oh, the number grew */
X GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + 2);
X str->str_cur++;
X for (d = str->str_ptr + str->str_cur; d > str->str_ptr; d--)
X *d = d[-1];
X *d = '1';
X}
X
Xvoid
Xstr_dec(str)
Xregister STR *str;
X{
X register char *d;
X
X if (!str)
X return;
X if (str->str_nok) {
X str->str_nval -= 1.0;
X str->str_pok = 0;
X return;
X }
X if (!str->str_pok) {
X str->str_nval = -1.0;
X str->str_nok = 1;
X return;
X }
X for (d = str->str_ptr; *d && *d != '.'; d++) ;
X d--;
X if (!isdigit(*str->str_ptr) || !isdigit(*d) || (*d == '0' && d == str->str_ptr)) {
X str_numset(str,atof(str->str_ptr) - 1.0); /* punt */
X return;
X }
X while (d >= str->str_ptr) {
X if (--*d >= '0')
X return;
X *(d--) = '9';
X }
X}
X
X/* make a string that will exist for the duration of the expression eval */
X
XSTR *
Xstr_static(oldstr)
XSTR *oldstr;
X{
X register STR *str = str_new(0);
X static long tmps_size = -1;
X
X str_sset(str,oldstr);
X if (++tmps_max > tmps_size) {
X tmps_size = tmps_max;
X if (!(tmps_size & 127)) {
X if (tmps_size)
X tmps_list = (STR**)saferealloc((char*)tmps_list,
X (tmps_size + 128) * sizeof(STR*) );
X else
X tmps_list = (STR**)safemalloc(128 * sizeof(char*));
X }
X }
X tmps_list[tmps_max] = str;
X return str;
X}
X
XSTR *
Xstr_make(s)
Xchar *s;
X{
X register STR *str = str_new(0);
X
X str_set(str,s);
X return str;
X}
X
XSTR *
Xstr_nmake(n)
Xdouble n;
X{
X register STR *str = str_new(0);
X
X str_numset(str,n);
X return str;
X}
!STUFFY!FUNK!
echo Extracting malloc.c
sed >malloc.c <<'!STUFFY!FUNK!' -e 's/X//'
X/* $Header: malloc.c,v 2.0 88/06/05 00:09:16 root Exp $
X *
X * $Log: malloc.c,v $
X * Revision 2.0 88/06/05 00:09:16 root
X * Baseline version 2.0.
X *
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)malloc.c 4.3 (Berkeley) 9/16/83";
X#endif
X
X#define RCHECK
X/*
X * malloc.c (Caltech) 2/21/82
X * Chris Kingsley, kingsley at cit-20.
X *
X * This is a very fast storage allocator. It allocates blocks of a small
X * number of different sizes, and keeps free lists of each size. Blocks that
X * don't exactly fit are passed up to the next larger size. In this
X * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long.
X * This is designed for use in a program that uses vast quantities of memory,
X * but bombs when it runs out.
X */
X
X#include "EXTERN.h"
X#include "perl.h"
X
X/* I don't much care whether these are defined in sys/types.h--LAW */
X
X#define u_char unsigned char
X#define u_int unsigned int
X#define u_short unsigned short
X
X/*
X * The overhead on a block is at least 4 bytes. When free, this space
X * contains a pointer to the next free block, and the bottom two bits must
X * be zero. When in use, the first byte is set to MAGIC, and the second
X * byte is the size index. The remaining bytes are for alignment.
X * If range checking is enabled and the size of the block fits
X * in two bytes, then the top two bytes hold the size of the requested block
X * plus the range checking words, and the header word MINUS ONE.
X */
Xunion overhead {
X union overhead *ov_next; /* when free */
X struct {
X u_char ovu_magic; /* magic number */
X u_char ovu_index; /* bucket # */
X#ifdef RCHECK
X u_short ovu_size; /* actual block size */
X u_int ovu_rmagic; /* range magic number */
X#endif
X } ovu;
X#define ov_magic ovu.ovu_magic
X#define ov_index ovu.ovu_index
X#define ov_size ovu.ovu_size
X#define ov_rmagic ovu.ovu_rmagic
X};
X
X#define MAGIC 0xff /* magic # on accounting info */
X#define OLDMAGIC 0x7f /* same after a free() */
X#define RMAGIC 0x55555555 /* magic # on range info */
X#ifdef RCHECK
X#define RSLOP sizeof (u_int)
X#else
X#define RSLOP 0
X#endif
X
X/*
X * nextf[i] is the pointer to the next free block of size 2^(i+3). The
X * smallest allocatable block is 8 bytes. The overhead information
X * precedes the data area returned to the user.
X */
X#define NBUCKETS 30
Xstatic union overhead *nextf[NBUCKETS];
Xextern char *sbrk();
X
X#ifdef MSTATS
X/*
X * nmalloc[i] is the difference between the number of mallocs and frees
X * for a given block size.
X */
Xstatic u_int nmalloc[NBUCKETS];
X#include <stdio.h>
X#endif
X
X#ifdef debug
X#define ASSERT(p) if (!(p)) botch("p"); else
Xstatic
Xbotch(s)
X char *s;
X{
X
X printf("assertion botched: %s\n", s);
X abort();
X}
X#else
X#define ASSERT(p)
X#endif
X
Xchar *
Xmalloc(nbytes)
X register unsigned nbytes;
X{
X register union overhead *p;
X register int bucket = 0;
X register unsigned shiftr;
X
X /*
X * Convert amount of memory requested into
X * closest block size stored in hash buckets
X * which satisfies request. Account for
X * space used per block for accounting.
X */
X nbytes += sizeof (union overhead) + RSLOP;
X nbytes = (nbytes + 3) &~ 3;
X shiftr = (nbytes - 1) >> 2;
X /* apart from this loop, this is O(1) */
X while (shiftr >>= 1)
X bucket++;
X /*
X * If nothing in hash bucket right now,
X * request more memory from the system.
X */
X if (nextf[bucket] == NULL)
X morecore(bucket);
X if ((p = (union overhead *)nextf[bucket]) == NULL)
X return (NULL);
X /* remove from linked list */
X if (*((int*)p) > 0x10000000)
X fprintf(stderr,"Corrupt malloc ptr 0x%x at 0x%x\n",*((int*)p),p);
X nextf[bucket] = nextf[bucket]->ov_next;
X p->ov_magic = MAGIC;
X p->ov_index= bucket;
X#ifdef MSTATS
X nmalloc[bucket]++;
X#endif
X#ifdef RCHECK
X /*
X * Record allocated size of block and
X * bound space with magic numbers.
X */
X if (nbytes <= 0x10000)
X p->ov_size = nbytes - 1;
X p->ov_rmagic = RMAGIC;
X *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
X#endif
X return ((char *)(p + 1));
X}
X
X/*
X * Allocate more memory to the indicated bucket.
X */
Xstatic
Xmorecore(bucket)
X register bucket;
X{
X register union overhead *op;
X register int rnu; /* 2^rnu bytes will be requested */
X register int nblks; /* become nblks blocks of the desired size */
X register int siz;
X
X if (nextf[bucket])
X return;
X /*
X * Insure memory is allocated
X * on a page boundary. Should
X * make getpageize call?
X */
X op = (union overhead *)sbrk(0);
X if ((int)op & 0x3ff)
X sbrk(1024 - ((int)op & 0x3ff));
X /* take 2k unless the block is bigger than that */
X rnu = (bucket <= 8) ? 11 : bucket + 3;
X nblks = 1 << (rnu - (bucket + 3)); /* how many blocks to get */
X if (rnu < bucket)
X rnu = bucket;
X op = (union overhead *)sbrk(1 << rnu);
X /* no more room! */
X if ((int)op == -1)
X return;
X /*
X * Round up to minimum allocation size boundary
X * and deduct from block count to reflect.
X */
X if ((int)op & 7) {
X op = (union overhead *)(((int)op + 8) &~ 7);
X nblks--;
X }
X /*
X * Add new memory allocated to that on
X * free list for this hash bucket.
X */
X nextf[bucket] = op;
X siz = 1 << (bucket + 3);
X while (--nblks > 0) {
X op->ov_next = (union overhead *)((caddr_t)op + siz);
X op = (union overhead *)((caddr_t)op + siz);
X }
X}
X
Xfree(cp)
X char *cp;
X{
X register int size;
X register union overhead *op;
X
X if (cp == NULL)
X return;
X op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
X#ifdef debug
X ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */
X#else
X if (op->ov_magic != MAGIC) {
X fprintf(stderr,"%s free() ignored\n",
X op->ov_magic == OLDMAGIC ? "Duplicate" : "Bad");
X return; /* sanity */
X }
X op->ov_magic = OLDMAGIC;
X#endif
X#ifdef RCHECK
X ASSERT(op->ov_rmagic == RMAGIC);
X if (op->ov_index <= 13)
X ASSERT(*(u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP) == RMAGIC);
X#endif
X ASSERT(op->ov_index < NBUCKETS);
X size = op->ov_index;
X op->ov_next = nextf[size];
X nextf[size] = op;
X#ifdef MSTATS
X nmalloc[size]--;
X#endif
X}
X
X/*
X * When a program attempts "storage compaction" as mentioned in the
X * old malloc man page, it realloc's an already freed block. Usually
X * this is the last block it freed; occasionally it might be farther
X * back. We have to search all the free lists for the block in order
X * to determine its bucket: 1st we make one pass thru the lists
X * checking only the first block in each; if that fails we search
X * ``reall_srchlen'' blocks in each list for a match (the variable
X * is extern so the caller can modify it). If that fails we just copy
X * however many bytes was given to realloc() and hope it's not huge.
X */
Xint reall_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */
X
Xchar *
Xrealloc(cp, nbytes)
X char *cp;
X unsigned nbytes;
X{
X register u_int onb;
X union overhead *op;
X char *res;
X register int i;
X int was_alloced = 0;
X
X if (cp == NULL)
X return (malloc(nbytes));
X op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
X if (op->ov_magic == MAGIC) {
X was_alloced++;
X i = op->ov_index;
X } else {
X /*
X * Already free, doing "compaction".
X *
X * Search for the old block of memory on the
X * free list. First, check the most common
X * case (last element free'd), then (this failing)
X * the last ``reall_srchlen'' items free'd.
X * If all lookups fail, then assume the size of
X * the memory block being realloc'd is the
X * smallest possible.
X */
X if ((i = findbucket(op, 1)) < 0 &&
X (i = findbucket(op, reall_srchlen)) < 0)
X i = 0;
X }
X onb = (1 << (i + 3)) - sizeof (*op) - RSLOP;
X /* avoid the copy if same size block */
X if (was_alloced &&
X nbytes <= onb && nbytes > (onb >> 1) - sizeof(*op) - RSLOP)
X return(cp);
X if ((res = malloc(nbytes)) == NULL)
X return (NULL);
X if (cp != res) /* common optimization */
X bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
X if (was_alloced)
X free(cp);
X return (res);
X}
X
X/*
X * Search ``srchlen'' elements of each free list for a block whose
X * header starts at ``freep''. If srchlen is -1 search the whole list.
X * Return bucket number, or -1 if not found.
X */
Xstatic
Xfindbucket(freep, srchlen)
X union overhead *freep;
X int srchlen;
X{
X register union overhead *p;
X register int i, j;
X
X for (i = 0; i < NBUCKETS; i++) {
X j = 0;
X for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
X if (p == freep)
X return (i);
X j++;
X }
X }
X return (-1);
X}
X
X#ifdef MSTATS
X/*
X * mstats - print out statistics about malloc
X *
X * Prints two lines of numbers, one showing the length of the free list
X * for each size category, the second showing the number of mallocs -
X * frees for each size category.
X */
Xmstats(s)
X char *s;
X{
X register int i, j;
X register union overhead *p;
X int totfree = 0,
X totused = 0;
X
X fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s);
X for (i = 0; i < NBUCKETS; i++) {
X for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
X ;
X fprintf(stderr, " %d", j);
X totfree += j * (1 << (i + 3));
X }
X fprintf(stderr, "\nused:\t");
X for (i = 0; i < NBUCKETS; i++) {
X fprintf(stderr, " %d", nmalloc[i]);
X totused += nmalloc[i] * (1 << (i + 3));
X }
X fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n",
X totused, totfree);
X}
X#endif
!STUFFY!FUNK!
echo Extracting MANIFEST
sed >MANIFEST <<'!STUFFY!FUNK!' -e 's/X//'
XAfter all the perl kits are run you should have the following files:
X
XFilename Kit Description
X-------- --- -----------
XChanges 13 Differences between 1.0 level 29 and 2.0 level 0
XConfigure 6 Run this first
XEXTERN.h 6 Included before foreign .h files
XINTERN.h 15 Included before domestic .h files
XMANIFEST 11 This list of files
XMakefile.SH 13 Precursor to Makefile
XREADME 1 The Instructions
XWishlist 4 Some things that may or may not happen
Xarg.c 1 Expression evaluation
Xarg.h 12 Public declarations for the above
Xarray.c 13 Numerically subscripted arrays
Xarray.h 15 Public declarations for the above
Xcmd.c 10 Command interpreter
Xcmd.h 13 Public declarations for the above
Xconfig.H 13 Sample config.h
Xconfig.h.SH 11 Produces config.h.
Xdump.c 12 Debugging output
Xeg/ADB 15 An adb wrapper to put in your crash dir
Xeg/README 1 Intro to example perl scripts
Xeg/changes 15 A program to list recently changed files
Xeg/dus 15 A program to do du -s on non-mounted dirs
Xeg/findcp 14 A find wrapper that implements a -cp switch
Xeg/findtar 15 A find wrapper that pumps out a tar file
Xeg/g/gcp 14 A program to do a global rcp
Xeg/g/gcp.man 14 Manual page for gcp
Xeg/g/ged 1 A program to do a global edit
Xeg/g/ghosts 15 A sample /etc/ghosts file
Xeg/g/gsh 10 A program to do a global rsh
Xeg/g/gsh.man 14 Manual page for gsh
Xeg/myrup 15 A program to find lightly loaded machines
Xeg/nih 15 Script to insert #! workaround
Xeg/rmfrom 15 A program to feed doomed filenames to
Xeg/scan/scan_df 14 Scan for filesystem anomalies
Xeg/scan/scan_last 14 Scan for login anomalies
Xeg/scan/scan_messages 13 Scan for console message anomalies
Xeg/scan/scan_passwd 15 Scan for passwd file anomalies
Xeg/scan/scan_ps 15 Scan for process anomalies
Xeg/scan/scan_sudo 14 Scan for sudo anomalies
Xeg/scan/scan_suid 8 Scan for setuid anomalies
Xeg/scan/scanner 14 An anomaly reporter
Xeg/shmkill 15 A program to remove unused shared memory
Xeg/van/empty 15 A program to empty the trashcan
Xeg/van/unvanish 14 A program to undo what vanish does
Xeg/van/vanexp 15 A program to expire vanished files
Xeg/van/vanish 14 A program to put files in a trashcan
Xeval.c 8 The expression evaluator
Xform.c 12 Format processing
Xform.h 15 Public declarations for the above
Xhandy.h 15 Handy definitions
Xhash.c 12 Associative arrays
Xhash.h 14 Public declarations for the above
Xlib/getopt.pl 14 Perl library supporting option parsing
Xlib/importenv.pl 15 Perl routine to get environment into variables.
Xlib/stat.pl 15 Perl library supporting stat function
Xmakedepend.SH 5 Precursor to makedepend
Xmakedir.SH 14 Precursor to makedir
Xmalloc.c 11 A version of malloc you might not want
Xpatchlevel.h 12 The current patch level of perl
Xperl.h 12 Global declarations
Xperl.man.1 5 The manual page(s), first half
Xperl.man.2 3 The manual page(s), second half
Xperl.y 10 Yacc grammar for perl
Xperldb 11 Perl symbolic debugger
Xperldb.man 13 Manual page for perl debugger
Xperlsh 15 A poor man's perl shell.
Xperly.c 4 The perl compiler
Xregexp.c 2 String matching
Xregexp.h 14 Public declarations for the above
Xspat.h 14 Search pattern declarations
Xstab.c 6 Symbol table stuff
Xstab.h 3 Public declarations for the above
Xstr.c 7 String handling package
Xstr.h 14 Public declarations for the above
Xt/README 1 Instructions for regression tests
Xt/TEST 14 The regression tester
Xt/base.cond 15 See if conditionals work
Xt/base.if 15 See if if works
Xt/base.lex 15 See if lexical items work
Xt/base.pat 15 See if pattern matching works
Xt/base.term 15 See if various terms work
Xt/cmd.elsif 15 See if else-if works
Xt/cmd.for 15 See if for loops work
Xt/cmd.mod 15 See if statement modifiers work
Xt/cmd.subval 14 See if subroutine values work
Xt/cmd.while 14 See if while loops work
Xt/comp.cmdopt 13 See if command optimization works
Xt/comp.cpp 15 See if C preprocessor works
Xt/comp.decl 15 See if declarations work
Xt/comp.multiline 15 See if multiline strings work
Xt/comp.script 14 See if script invokation works
Xt/comp.term 15 See if more terms work
Xt/io.argv 15 See if ARGV stuff works
Xt/io.dup 15 See if >& works right
Xt/io.fs 12 See if directory manipulations work
Xt/io.inplace 15 See if inplace editing works
Xt/io.pipe 15 See if secure pipes work
Xt/io.print 15 See if print commands work
Xt/io.tell 13 See if file seeking works
Xt/op.append 15 See if . works
Xt/op.auto 14 See if autoincrement et all work
Xt/op.chop 15 See if chop works
Xt/op.cond 5 See if conditional expressions work
Xt/op.delete 15 See if delete works
Xt/op.do 14 See if subroutines work
Xt/op.each 14 See if associative iterators work
Xt/op.eval 14 See if eval operator works
Xt/op.exec 15 See if exec and system work
Xt/op.exp 15 See if math functions work
Xt/op.flip 15 See if range operator works
Xt/op.fork 15 See if fork works
Xt/op.goto 15 See if goto works
Xt/op.int 15 See if int works
Xt/op.join 15 See if join works
Xt/op.list 14 See if array lists work
Xt/op.magic 15 See if magic variables work
Xt/op.oct 15 See if oct and hex work
Xt/op.ord 15 See if ord works
Xt/op.pat 14 See if esoteric patterns work
Xt/op.push 15 See if push and pop work
Xt/op.regexp 15 See if regular expressions work
Xt/op.repeat 15 See if x operator works
Xt/op.sleep 15 See if sleep works
Xt/op.split 7 See if split works
Xt/op.sprintf 15 See if sprintf works
Xt/op.stat 11 See if stat works
Xt/op.study 14 See if study works
Xt/op.subst 14 See if substitutions work
Xt/op.time 14 See if time functions work
Xt/op.unshift 15 See if unshift works
Xt/re_tests 13 Input file for op.regexp
Xtoke.c 9 The tokener
Xutil.c 8 Utility routines
Xutil.h 15 Public declarations for the above
Xversion.c 15 Prints version of perl
Xx2p/EXTERN.h 15 Same as above
Xx2p/INTERN.h 15 Same as above
Xx2p/Makefile.SH 4 Precursor to Makefile
Xx2p/a2p.h 13 Global declarations
Xx2p/a2p.man 12 Manual page for awk to perl translator
Xx2p/a2p.y 12 A yacc grammer for awk
Xx2p/a2py.c 9 Awk compiler, sort of
Xx2p/handy.h 15 Handy definitions
Xx2p/hash.c 13 Associative arrays again
Xx2p/hash.h 14 Public declarations for the above
Xx2p/s2p 10 Sed to perl translator
Xx2p/s2p.man 9 Manual page for sed to perl translator
Xx2p/str.c 11 String handling package
Xx2p/str.h 15 Public declarations for the above
Xx2p/util.c 13 Utility routines
Xx2p/util.h 15 Public declarations for the above
Xx2p/walk.c 7 Parse tree walker
!STUFFY!FUNK!
echo Extracting config.h.SH
sed >config.h.SH <<'!STUFFY!FUNK!' -e 's/X//'
Xcase $CONFIG in
X'')
X if test ! -f config.sh; then
X ln ../config.sh . || \
X ln ../../config.sh . || \
X ln ../../../config.sh . || \
X (echo "Can't find config.sh."; exit 1)
X echo "Using config.sh from above..."
X fi
X . ./config.sh
X ;;
Xesac
Xecho "Extracting config.h (with variable substitutions)"
Xcat <<!GROK!THIS! >config.h
X/* config.h
X * This file was produced by running the config.h.SH script, which
X * gets its values from config.sh, which is generally produced by
X * running Configure.
X *
X * Feel free to modify any of this as the need arises. Note, however,
X * that running config.h.SH again will wipe out any changes you've made.
X * For a more permanent change edit config.sh and rerun config.h.SH.
X */
X
X
X/* EUNICE:
X * This symbol, if defined, indicates that the program is being compiled
X * under the EUNICE package under VMS. The program will need to handle
X * things like files that don't go away the first time you unlink them,
X * due to version numbering. It will also need to compensate for lack
X * of a respectable link() command.
X */
X/* VMS:
X * This symbol, if defined, indicates that the program is running under
X * VMS. It is currently only set in conjunction with the EUNICE symbol.
X */
X#$d_eunice EUNICE /**/
X#$d_eunice VMS /**/
X
X/* CPPSTDIN:
X * This symbol contains the first part of the string which will invoke
X * the C preprocessor on the standard input and produce to standard
X * output. Typical value of "cc -E" or "/lib/cpp".
X */
X/* CPPMINUS:
X * This symbol contains the second part of the string which will invoke
X * the C preprocessor on the standard input and produce to standard
X * output. This symbol will have the value "-" if CPPSTDIN needs a minus
X * to specify standard input, otherwise the value is "".
X */
X#define CPPSTDIN "$cppstdin"
X#define CPPMINUS "$cppminus"
X
X/* BCOPY:
X * This symbol, if defined, indicates that the bcopy routine is available
X * to copy blocks of memory. Otherwise you should probably use memcpy().
X */
X#$d_bcopy BCOPY /**/
X
X/* CHARSPRINTF:
X * This symbol is defined if this system declares "char *sprintf()" in
X * stdio.h. The trend seems to be to declare it as "int sprintf()". It
X * is up to the package author to declare sprintf correctly based on the
X * symbol.
X */
X#$d_charsprf CHARSPRINTF /**/
X
X/* CRYPT:
X * This symbol, if defined, indicates that the crypt routine is available
X * to encrypt passwords and the like.
X */
X#$d_crypt CRYPT /**/
X
X/* FCHMOD:
X * This symbol, if defined, indicates that the fchmod routine is available
X * to change mode of opened files. If unavailable, use chmod().
X */
X#$d_fchmod FCHMOD /**/
X
X/* FCHOWN:
X * This symbol, if defined, indicates that the fchown routine is available
X * to change ownership of opened files. If unavailable, use chown().
X */
X#$d_fchown FCHOWN /**/
X
X/* GETGROUPS:
X * This symbol, if defined, indicates that the getgroups() routine is
X * available to get the list of process groups. If unavailable, multiple
X * groups are probably not supported.
X */
X#$d_getgrps GETGROUPS /**/
X
X/* index:
X * This preprocessor symbol is defined, along with rindex, if the system
X * uses the strchr and strrchr routines instead.
X */
X/* rindex:
X * This preprocessor symbol is defined, along with index, if the system
X * uses the strchr and strrchr routines instead.
X */
X#$d_index index strchr /* cultural */
X#$d_index rindex strrchr /* differences? */
X
X/* KILLPG:
X * This symbol, if defined, indicates that the killpg routine is available
X * to kill process groups. If unavailable, you probably should use kill
X * with a negative process number.
X */
X#$d_killpg KILLPG /**/
X
X/* MEMCPY:
X * This symbol, if defined, indicates that the memcpy routine is available
X * to copy blocks of memory. Otherwise you should probably use bcopy().
X * If neither is defined, roll your own.
X */
X#$d_memcpy MEMCPY /**/
X
X/* RENAME:
X * This symbol, if defined, indicates that the rename routine is available
X * to rename files. Otherwise you should do the unlink(), link(), unlink()
X * trick.
X */
X#$d_rename RENAME /**/
X
X/* SETEGID:
X * This symbol, if defined, indicates that the setegid routine is available
X * to change the effective gid of the current program.
X */
X#$d_setegid SETEGID /**/
X
X/* SETEUID:
X * This symbol, if defined, indicates that the seteuid routine is available
X * to change the effective uid of the current program.
X */
X#$d_seteuid SETEUID /**/
X
X/* SETRGID:
X * This symbol, if defined, indicates that the setrgid routine is available
X * to change the real gid of the current program.
X */
X#$d_setrgid SETRGID /**/
X
X/* SETRUID:
X * This symbol, if defined, indicates that the setruid routine is available
X * to change the real uid of the current program.
X */
X#$d_setruid SETRUID /**/
X
X/* STATBLOCKS:
X * This symbol is defined if this system has a stat structure declaring
X * st_blksize and st_blocks.
X */
X#$d_statblks STATBLOCKS /**/
X
X/* STDSTDIO:
X * This symbol is defined if this system has a FILE structure declaring
X * _ptr and _cnt in stdio.h.
X */
X#$d_stdstdio STDSTDIO /**/
X
X/* STRCSPN:
X * This symbol, if defined, indicates that the strcspn routine is available
X * to scan strings.
X */
X#$d_strcspn STRCSPN /**/
X
X/* STRUCTCOPY:
X * This symbol, if defined, indicates that this C compiler knows how
X * to copy structures. If undefined, you'll need to use a block copy
X * routine of some sort instead.
X */
X#$d_strctcpy STRUCTCOPY /**/
X
X/* SYMLINK:
X * This symbol, if defined, indicates that the symlink routine is available
X * to create symbolic links.
X */
X#$d_symlink SYMLINK /**/
X
X/* TMINSYS:
X * This symbol is defined if this system declares "struct tm" in
X * in <sys/time.h> rather than <time.h>. We can't just say
X * -I/usr/include/sys because some systems have both time files, and
X * the -I trick gets the wrong one.
X */
X#$d_tminsys TMINSYS /**/
X
X/* vfork:
X * This symbol, if defined, remaps the vfork routine to fork if the
X * vfork() routine isn't supported here.
X */
X#$d_vfork vfork fork /**/
X
X/* VOIDSIG:
X * This symbol is defined if this system declares "void (*signal())()" in
X * signal.h. The old way was to declare it as "int (*signal())()". It
X * is up to the package author to declare things correctly based on the
X * symbol.
X */
X#$d_voidsig VOIDSIG /**/
X
X/* GIDTYPE:
X * This symbol has a value like gid_t, int, ushort, or whatever type is
X * used to declare group ids in the kernel.
X */
X#define GIDTYPE $gidtype /**/
X
X/* STDCHAR:
X * This symbol is defined to be the type of char used in stdio.h.
X * It has the values "unsigned char" or "char".
X */
X#define STDCHAR $stdchar /**/
X
X/* UIDTYPE:
X * This symbol has a value like uid_t, int, ushort, or whatever type is
X * used to declare user ids in the kernel.
X */
X#define UIDTYPE $uidtype /**/
X
X/* VOIDFLAGS:
X * This symbol indicates how much support of the void type is given by this
X * compiler. What various bits mean:
X *
X * 1 = supports declaration of void
X * 2 = supports arrays of pointers to functions returning void
X * 4 = supports comparisons between pointers to void functions and
X * addresses of void functions
X *
X * The package designer should define VOIDUSED to indicate the requirements
X * of the package. This can be done either by #defining VOIDUSED before
X * including config.h, or by defining defvoidused in Myinit.U. If the
X * level of void support necessary is not present, defines void to int.
X */
X#ifndef VOIDUSED
X#define VOIDUSED $defvoidused
X#endif
X#define VOIDFLAGS $voidflags
X#if (VOIDFLAGS & VOIDUSED) != VOIDUSED
X#$define void int /* is void to be avoided? */
X#$define M_VOID /* Xenix strikes again */
X#endif
X
X/* PRIVLIB:
X * This symbol contains the name of the private library for this package.
X * The library is private in the sense that it needn't be in anyone's
X * execution path, but it should be accessible by the world.
X */
X#define PRIVLIB "$privlib" /**/
X
X!GROK!THIS!
!STUFFY!FUNK!
echo Extracting perldb
sed >perldb <<'!STUFFY!FUNK!' -e 's/X//'
X#!/usr/bin/perl
X
X# $Header: perldb,v 2.0 88/06/05 00:09:45 root Exp $
X#
X# $Log: perldb,v $
X# Revision 2.0 88/06/05 00:09:45 root
X# Baseline version 2.0.
X#
X#
X
X$tmp = "/tmp/pdb$$"; # default temporary file, -o overrides.
X
X# parse any switches
X
Xwhile ($ARGV[0] =~ /^-/) {
X $_ = shift;
X /^-o$/ && ($tmp = shift,next);
X die "Unrecognized switch: $_";
X}
X
X$filename = shift;
Xdie "Usage: perldb [-o output] scriptname arguments" unless $filename;
X
Xopen(script,$filename) || die "Can't find $filename";
X
Xopen(tmp, ">$tmp") || die "Can't make temp script";
X
X$perl = '/usr/bin/perl';
X$init = 1;
X$state = 'statement';
X
X# now translate script to contain DB calls at the appropriate places
X
Xwhile (<script>) {
X chop;
X if ($. == 1) {
X if (/^#! *([^ \t]*) (-[^ \t]*)/) {
X $perl = $1;
X $switch = $2;
X }
X elsif (/^#! *([^ \t]*)/) {
X $perl = $1;
X }
X }
X s/ *$//;
X push(@script,$_); # remember line for DBinit
X $line = $_;
X next if /^$/; # blank lines are uninteresting
X next if /^[ \t]*#/; # likewise comment lines
X if ($init) {
X print tmp "do DBinit($.);"; $init = '';
X }
X if ($inform) { # skip formats
X if (/^\.$/) {
X $inform = '';
X $state = 'statement';
X }
X next;
X }
X if (/^[ \t]*format /) {
X $inform++;
X next;
X }
X if ($state eq 'statement' &&
X !/^[ \t]*}|^[ \t]*else|^[ \t]*continue|^[ \t]*elsif/) {
X if (s/^([ \t]*[A-Za-z_0-9]+:)//) {
X $label = $1;
X }
X else {
X $label = '';
X }
X $line = $label . "do DB($.); " . $_; # all that work for this line
X }
X else {
X $script[$#script - 1] .= ' '; # mark line as having continuation
X }
X do parse(); # set $state to correct eol value
X}
Xcontinue {
X print tmp $line,"\n";
X}
X
X# now put out our debugging subroutines. First the one that's called all over.
X
Xprint tmp '
Xsub DB {
X push(@DB,$. ,$@, $!, $[, $,, $/, $\ );
X $[ = 0; $, = ""; $/ = "\n"; $\ = "";
X $DBline=pop(@_);
X if ($DBsingle || $DBstop[$DBline] || $DBtrace) {
X print "$DBline:\t",$DBline[$DBline],"\n";
X for ($DBi = $DBline; $DBline[$DBi++] =~ / $/; ) {
X print "$DBi:\t",$DBline[$DBi],"\n";
X }
X }
X if ($DBaction[$DBline]) {
X eval $DBaction[$DBline]; print $@;
X }
X if ($DBstop[$DBline] || $DBsingle) {
X for (;;) {
X print "perldb> ";
X $DBcmd = <stdin>;
X last if $DBcmd =~ /^$/;
X if ($DBcmd =~ /^q$/) {
X exit 0;
X }
X if ($DBcmd =~ /^h$/) {
X print "
Xs Single step.
Xc Continue.
X<CR> Repeat last s or c.
Xl min-max List lines.
Xl line List line.
Xl List the whole program.
XL List breakpoints.
Xt Toggle trace mode.
Xb line Set breakpoint.
Xd line Delete breakpoint.
Xd Delete breakpoint at this line.
Xa line command Set an action for this line.
Xq Quit.
Xcommand Execute as a perl statement.
X
X";
X next;
X }
X if ($DBcmd =~ /^t$/) {
X $DBtrace = !$DBtrace;
X print "Trace = $DBtrace\n";
X next;
X }
X if ($DBcmd =~ /^l (.*)[-,](.*)/) {
X for ($DBi = $1; $DBi <= $2; $DBi++) {
X print "$DBi:\t", $DBline[$DBi], "\n";
X }
X next;
X }
X if ($DBcmd =~ /^l (.*)/) {
X print "$1:\t", $DBline[$1], "\n";
X next;
X }
X if ($DBcmd =~ /^l$/) {
X for ($DBi = 1; $DBi <= $DBmax ; $DBi++) {
X print "$DBi:\t", $DBline[$DBi], "\n";
X }
X next;
X }
X if ($DBcmd =~ /^L$/) {
X for ($DBi = 1; $DBi <= $DBmax ; $DBi++) {
X print "$DBi:\t", $DBline[$DBi], "\n" if $DBstop[$DBi];
X }
X next;
X }
X if ($DBcmd =~ /^b (.*)/) {
X $DBi = $1;
X if ($DBline[$DBi-1] =~ / $/) {
X print "Line $DBi not breakable.\n";
X }
X else {
X $DBstop[$DBi] = 1;
X }
X next;
X }
X if ($DBcmd =~ /^d (.*)/) {
X $DBstop[$1] = 0;
X next;
X }
X if ($DBcmd =~ /^d$/) {
X $DBstop[$DBline] = 0;
X next;
X }
X if ($DBcmd =~ /^a ([0-9]+)[ \t]+(.*)/) {
X $DBi = $1;
X $DBaction = $2;
X $DBaction .= ";" unless $DBaction =~ /[;}]$/;
X $DBaction[$DBi] = $DBaction;
X next;
X }
X if ($DBcmd =~ /^s$/) {
X $DBsingle = 1;
X last;
X }
X if ($DBcmd =~ /^c$/) {
X $DBsingle = 0;
X last;
X }
X chop($DBcmd);
X $DBcmd .= ";" unless $DBcmd =~ /[;}]$/;
X eval $DBcmd;
X print $@,"\n";
X }
X }
X $\ = pop(@DB);
X $/ = pop(@DB);
X $, = pop(@DB);
X $[ = pop(@DB);
X $! = pop(@DB);
X $@ = pop(@DB);
X $. = pop(@DB);
X}
X
Xsub DBinit {
X $DBstop[$_[0]] = 1;
X';
Xprint tmp " \$0 = '$script';\n";
Xprint tmp " \$DBmax = $.;\n";
Xprint tmp " unlink '/tmp/pdb$$';\n"; # expected to fail on -o.
Xfor ($i = 1; $#script >= 0; $i++) {
X $_ = shift(@script);
X s/'/\\'/g;
X print tmp " \$DBline[$i] = '$_';\n";
X}
Xprint tmp '}
X';
X
Xclose tmp;
X
X# prepare to run the new script
X
Xunshift(@ARGV,$tmp);
Xunshift(@ARGV,$switch) if $switch;
Xunshift(@ARGV,$perl);
Xexec @ARGV;
X
X# This routine tokenizes one perl line good enough to tell what state we are
X# in by the end of the line, so we can tell if the next line should contain
X# a call to DB or not.
X
Xsub parse {
X until ($_ eq '') {
X $ord = ord($_);
X if ($quoting) {
X if ($quote == $ord) {
X $quoting--;
X }
X s/^.// if /^[\\]/;
X s/^.//;
X last if $_ eq "\n";
X $state = 'term' unless $quoting;
X next;
X }
X if ($ord > 64) {
X do quote(ord($1),1), next if s/^m\b(.)//;
X do quote(ord($1),2), next if s/^s\b(.)//;
X do quote(ord($1),2), next if s/^y\b(.)//;
X do quote(ord($1),2), next if s/^tr\b(.)//;
X do quote($ord,1), next if s/^`//;
X next if s/^[A-Za-z_][A-Za-z_0-9]*://;
X $state = 'term', next if s/^eof\b//;
X $state = 'term', next if s/^shift\b//;
X $state = 'term', next if s/^split\b//;
X $state = 'term', next if s/^tell\b//;
X $state = 'term', next if s/^write\b//;
X $state = 'operator', next if s/^[A-Za-z_][A-Za-z_0-9]*//;
X $state = 'operator', next if s/^[~^|]+//;
X $state = 'statement', next if s/^{//;
X $state = 'statement', next if s/^}[ \t]*$//;
X $state = 'statement', next if s/^}[ \t]*#/#/;
X $state = 'term', next if s/^}//;
X $state = 'operator', next if s/^\[//;
X $state = 'term', next if s/^]//;
X die "Illegal character $_";
X }
X elsif ($ord < 33) {
X next if s/[ \t\n\f]+//;
X die "Illegal character $_";
X }
X else {
X $state = 'statement', next if s/^;//;
X $state = 'term', next if s/^\.[0-9eE]+//;
X $state = 'term', next if s/^[0-9][0-9xaAbBcCddeEfF.]*//;
X $state = 'term', next if s/^\$[A-Za-z_][A-Za-z_0-9]*//;
X $state = 'term', next if s/^\$.//;
X $state = 'term', next if s/^@[A-Za-z_][A-Za-z_0-9]*//;
X $state = 'term', next if s/^@.//;
X $state = 'term', next if s/^<[A-Za-z_0-9]*>//;
X next if s/^\+\+//;
X next if s/^--//;
X $state = 'operator', next if s/^[-(!%&*=+:,.<>]//;
X $state = 'term', next if s/^\)+//;
X do quote($ord,1), next if s/^'//;
X do quote($ord,1), next if s/^"//;
X if (s|^[/?]||) {
X if ($state =~ /stat|oper/) {
X $state = 'term';
X do quote($ord,1), next;
X }
X $state = 'operator', next;
X }
X next if s/^#.*//;
X }
X }
X}
X
Xsub quote {
X ($quote,$quoting) = @_;
X $state = 'quote';
X}
!STUFFY!FUNK!
echo Extracting t/op.stat
sed >t/op.stat <<'!STUFFY!FUNK!' -e 's/X//'
X#!./perl
X
X# $Header: op.stat,v 2.0 88/06/05 00:14:43 root Exp $
X
Xprint "1..56\n";
X
Xopen(foo, ">Op.stat.tmp");
X
X($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
X $blksize,$blocks) = stat(foo);
Xif ($nlink == 1) {print "ok 1\n";} else {print "not ok 1\n";}
Xif ($mtime && $mtime == $ctime) {print "ok 2\n";} else {print "not ok 2\n";}
X
Xprint foo "Now is the time for all good men to come to.\n";
Xclose(foo);
X
X$base = time;
Xwhile (time == $base) {}
X
X`rm -f Op.stat.tmp2; ln Op.stat.tmp Op.stat.tmp2; chmod 644 Op.stat.tmp`;
X
X($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
X $blksize,$blocks) = stat('Op.stat.tmp');
X
Xif ($nlink == 2) {print "ok 3\n";} else {print "not ok 3\n";}
Xif ($mtime && $mtime != $ctime) {print "ok 4\n";} else {print "not ok 4\n";}
Xprint "#4 :$mtime: != :$ctime:\n";
X
X`cp /dev/null Op.stat.tmp`;
X
Xif (-z 'Op.stat.tmp') {print "ok 5\n";} else {print "not ok 5\n";}
Xif (! -s 'Op.stat.tmp') {print "ok 6\n";} else {print "not ok 6\n";}
X
X`echo hi >Op.stat.tmp`;
Xif (! -z 'Op.stat.tmp') {print "ok 7\n";} else {print "not ok 7\n";}
Xif (-s 'Op.stat.tmp') {print "ok 8\n";} else {print "not ok 8\n";}
X
Xchmod 0,'Op.stat.tmp';
X$olduid = $>; # can't test -r if uid == 0
Xeval '$> = 1;'; # so switch uid (may not be implemented)
Xif (!$> || ! -r 'Op.stat.tmp') {print "ok 9\n";} else {print "not ok 9\n";}
Xif (!$> || ! -w 'Op.stat.tmp') {print "ok 10\n";} else {print "not ok 10\n";}
Xeval '$> = $olduid;'; # switch uid back (may not be implemented)
Xif (! -x 'Op.stat.tmp') {print "ok 11\n";} else {print "not ok 11\n";}
X
Xforeach ((12,13,14,15,16,17)) {
X print "ok $_\n"; #deleted tests
X}
X
Xchmod 0700,'Op.stat.tmp';
Xif (-r 'Op.stat.tmp') {print "ok 18\n";} else {print "not ok 18\n";}
Xif (-w 'Op.stat.tmp') {print "ok 19\n";} else {print "not ok 19\n";}
Xif (-x 'Op.stat.tmp') {print "ok 20\n";} else {print "not ok 20\n";}
X
Xif (-f 'Op.stat.tmp') {print "ok 21\n";} else {print "not ok 21\n";}
Xif (! -d 'Op.stat.tmp') {print "ok 22\n";} else {print "not ok 22\n";}
X
Xif (-d '.') {print "ok 23\n";} else {print "not ok 23\n";}
Xif (! -f '.') {print "ok 24\n";} else {print "not ok 24\n";}
X
Xif (`ls -l perl` =~ /^l.*->/) {
X if (-l 'perl') {print "ok 25\n";} else {print "not ok 25\n";}
X}
Xelse {
X print "ok 25\n";
X}
X
Xif (-o 'Op.stat.tmp') {print "ok 26\n";} else {print "not ok 26\n";}
X
Xif (-e 'Op.stat.tmp') {print "ok 27\n";} else {print "not ok 27\n";}
X`rm -f Op.stat.tmp Op.stat.tmp2`;
Xif (! -e 'Op.stat.tmp') {print "ok 28\n";} else {print "not ok 28\n";}
X
Xif (-c '/dev/tty') {print "ok 29\n";} else {print "not ok 29\n";}
Xif (! -c '.') {print "ok 30\n";} else {print "not ok 30\n";}
X
Xif (! -e '/dev/printer' || -S '/dev/printer')
X {print "ok 31\n";}
Xelse
X {print "not ok 31\n";}
Xif (! -S '.') {print "ok 32\n";} else {print "not ok 32\n";}
X
Xif (! -e '/dev/mt0' || -b '/dev/mt0')
X {print "ok 33\n";}
Xelse
X {print "not ok 33\n";}
Xif (! -b '.') {print "ok 34\n";} else {print "not ok 34\n";}
X
X$cnt = $uid = 0;
X
Xwhile (</usr/bin/*>) {
X $cnt++;
X $uid++ if -u;
X last if $uid && $uid < $cnt;
X}
X
X# I suppose this is going to fail somewhere...
Xif ($uid > 0 && $uid < $cnt) {print "ok 35\n";} else {print "not ok 35\n";}
X
Xunless (open(tty,"/dev/tty")) {
X print stderr "Can't open /dev/tty--run t/TEST outside of make.\n";
X}
Xif (-t tty) {print "ok 36\n";} else {print "not ok 36\n";}
Xif (-c tty) {print "ok 37\n";} else {print "not ok 37\n";}
Xclose(tty);
Xif (! -t tty) {print "ok 38\n";} else {print "not ok 38\n";}
Xopen(null,"/dev/null");
Xif (! -t null) {print "ok 39\n";} else {print "not ok 39\n";}
Xclose(null);
Xif (-t) {print "ok 40\n";} else {print "not ok 40\n";}
X
X# These aren't strictly "stat" calls, but so what?
X
Xif (-T 'op.stat') {print "ok 41\n";} else {print "not ok 41\n";}
Xif (! -B 'op.stat') {print "ok 42\n";} else {print "not ok 42\n";}
X
Xif (-B './perl') {print "ok 43\n";} else {print "not ok 43\n";}
Xif (! -T './perl') {print "ok 44\n";} else {print "not ok 44\n";}
X
Xopen(foo,'op.stat');
Xif (-T foo) {print "ok 45\n";} else {print "not ok 45\n";}
Xif (! -B foo) {print "ok 46\n";} else {print "not ok 46\n";}
X$_ = <foo>;
Xif (/perl/) {print "ok 47\n";} else {print "not ok 47\n";}
Xif (-T foo) {print "ok 48\n";} else {print "not ok 48\n";}
Xif (! -B foo) {print "ok 49\n";} else {print "not ok 49\n";}
Xclose(foo);
X
Xopen(foo,'op.stat');
X$_ = <foo>;
Xif (/perl/) {print "ok 50\n";} else {print "not ok 50\n";}
Xif (-T foo) {print "ok 51\n";} else {print "not ok 51\n";}
Xif (! -B foo) {print "ok 52\n";} else {print "not ok 52\n";}
Xseek(foo,0,0);
Xif (-T foo) {print "ok 53\n";} else {print "not ok 53\n";}
Xif (! -B foo) {print "ok 54\n";} else {print "not ok 54\n";}
Xclose(foo);
X
Xif (-T '/dev/null') {print "ok 55\n";} else {print "not ok 55\n";}
Xif (-B '/dev/null') {print "ok 56\n";} else {print "not ok 56\n";}
!STUFFY!FUNK!
echo ""
echo "End of kit 11 (of 15)"
cat /dev/null >kit11isdone
run=''
config=''
for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
if test -f kit${iskit}isdone; then
run="$run $iskit"
else
todo="$todo $iskit"
fi
done
case $todo in
'')
echo "You have run all your kits. Please read README and then type Configure."
chmod 755 Configure
;;
*) echo "You have run$run."
echo "You still need to run$todo."
;;
esac
: Someone might mail this, so...
exit
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Comp.sources.unix
mailing list