lwall@netlabs.com (Larry Wall) (04/16/91)
Submitted-by: Larry Wall <lwall@netlabs.com> Posting-number: Volume 18, Issue 29 Archive-name: perl/part11 [There are 36 kits for perl version 4.0.] #! /bin/sh # Make a new directory for the perl sources, cd to it, and run kits 1 # thru 36 through sh. When all 36 kits have been run, read README. echo "This is perl 4.0 kit 11 (of 36). If kit 11 is complete, the line" echo '"'"End of kit 11 (of 36)"'" will echo at the end.' echo "" export PATH || (echo "You didn't use sh, you clunch." ; kill $$) mkdir 2>/dev/null echo Extracting dolist.c sed >dolist.c <<'!STUFFY!FUNK!' -e 's/X//' X/* $Header: dolist.c,v 4.0 91/03/20 01:08:03 lwall Locked $ X * X * Copyright (c) 1989, Larry Wall X * X * You may distribute under the terms of the GNU General Public License X * as specified in the README file that comes with the perl 3.0 kit. X * X * $Log: dolist.c,v $ X * Revision 4.0 91/03/20 01:08:03 lwall X * 4.0 baseline. X * X */ X X#include "EXTERN.h" X#include "perl.h" X X X#ifdef BUGGY_MSC X #pragma function(memcmp) X#endif /* BUGGY_MSC */ X Xint Xdo_match(str,arg,gimme,arglast) XSTR *str; Xregister ARG *arg; Xint gimme; Xint *arglast; X{ X register STR **st = stack->ary_array; X register SPAT *spat = arg[2].arg_ptr.arg_spat; X register char *t; X register int sp = arglast[0] + 1; X STR *srchstr = st[sp]; X register char *s = str_get(st[sp]); X char *strend = s + st[sp]->str_cur; X STR *tmpstr; X char *myhint = hint; X X hint = Nullch; X if (!spat) { X if (gimme == G_ARRAY) X return --sp; X str_set(str,Yes); X STABSET(str); X st[sp] = str; X return sp; X } X if (!s) X fatal("panic: do_match"); X if (spat->spat_flags & SPAT_USED) { X#ifdef DEBUGGING X if (debug & 8) X deb("2.SPAT USED\n"); X#endif X if (gimme == G_ARRAY) X return --sp; X str_set(str,No); X STABSET(str); X st[sp] = str; X return sp; X } X --sp; X if (spat->spat_runtime) { X nointrp = "|)"; X sp = eval(spat->spat_runtime,G_SCALAR,sp); X st = stack->ary_array; X t = str_get(tmpstr = st[sp--]); X nointrp = ""; X#ifdef DEBUGGING X if (debug & 8) X deb("2.SPAT /%s/\n",t); X#endif X if (spat->spat_regexp) { X regfree(spat->spat_regexp); X spat->spat_regexp = Null(REGEXP*); /* crucial if regcomp aborts */ X } X spat->spat_regexp = regcomp(t,t+tmpstr->str_cur, X spat->spat_flags & SPAT_FOLD); X if (!*spat->spat_regexp->precomp && lastspat) X spat = lastspat; X if (spat->spat_flags & SPAT_KEEP) { X if (spat->spat_runtime) X arg_free(spat->spat_runtime); /* it won't change, so */ X spat->spat_runtime = Nullarg; /* no point compiling again */ X } X if (!spat->spat_regexp->nparens) X gimme = G_SCALAR; /* accidental array context? */ X if (regexec(spat->spat_regexp, s, strend, s, 0, X srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr, X gimme == G_ARRAY)) { X if (spat->spat_regexp->subbase) X curspat = spat; X lastspat = spat; X goto gotcha; X } X else { X if (gimme == G_ARRAY) X return sp; X str_sset(str,&str_no); X STABSET(str); X st[++sp] = str; X return sp; X } X } X else { X#ifdef DEBUGGING X if (debug & 8) { X char ch; X X if (spat->spat_flags & SPAT_ONCE) X ch = '?'; X else X ch = '/'; X deb("2.SPAT %c%s%c\n",ch,spat->spat_regexp->precomp,ch); X } X#endif X if (!*spat->spat_regexp->precomp && lastspat) X spat = lastspat; X t = s; X if (myhint) { X if (myhint < s || myhint > strend) X fatal("panic: hint in do_match"); X s = myhint; X if (spat->spat_regexp->regback >= 0) { X s -= spat->spat_regexp->regback; X if (s < t) X s = t; X } X else X s = t; X } X else if (spat->spat_short) { X if (spat->spat_flags & SPAT_SCANFIRST) { X if (srchstr->str_pok & SP_STUDIED) { X if (screamfirst[spat->spat_short->str_rare] < 0) X goto nope; X else if (!(s = screaminstr(srchstr,spat->spat_short))) X goto nope; X else if (spat->spat_flags & SPAT_ALL) X goto yup; X } X#ifndef lint X else if (!(s = fbminstr((unsigned char*)s, X (unsigned char*)strend, spat->spat_short))) X goto nope; X#endif X else if (spat->spat_flags & SPAT_ALL) X goto yup; X if (s && spat->spat_regexp->regback >= 0) { X ++spat->spat_short->str_u.str_useful; X s -= spat->spat_regexp->regback; X if (s < t) X s = t; X } X else X s = t; X } X else if (!multiline && (*spat->spat_short->str_ptr != *s || X bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) )) X goto nope; X if (--spat->spat_short->str_u.str_useful < 0) { X str_free(spat->spat_short); X spat->spat_short = Nullstr; /* opt is being useless */ X } X } X if (!spat->spat_regexp->nparens) X gimme = G_SCALAR; /* accidental array context? */ X if (regexec(spat->spat_regexp, s, strend, t, 0, X srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr, X gimme == G_ARRAY)) { X if (spat->spat_regexp->subbase) X curspat = spat; X lastspat = spat; X if (spat->spat_flags & SPAT_ONCE) X spat->spat_flags |= SPAT_USED; X goto gotcha; X } X else { X if (gimme == G_ARRAY) X return sp; X str_sset(str,&str_no); X STABSET(str); X st[++sp] = str; X return sp; X } X } X /*NOTREACHED*/ X X gotcha: X if (gimme == G_ARRAY) { X int iters, i, len; X X iters = spat->spat_regexp->nparens; X if (sp + iters >= stack->ary_max) { X astore(stack,sp + iters, Nullstr); X st = stack->ary_array; /* possibly realloced */ X } X X for (i = 1; i <= iters; i++) { X st[++sp] = str_mortal(&str_no); X if (s = spat->spat_regexp->startp[i]) { X len = spat->spat_regexp->endp[i] - s; X if (len > 0) X str_nset(st[sp],s,len); X } X } X return sp; X } X else { X str_sset(str,&str_yes); X STABSET(str); X st[++sp] = str; X return sp; X } X Xyup: X ++spat->spat_short->str_u.str_useful; X lastspat = spat; X if (spat->spat_flags & SPAT_ONCE) X spat->spat_flags |= SPAT_USED; X if (sawampersand) { X char *tmps; X X if (spat->spat_regexp->subbase) X Safefree(spat->spat_regexp->subbase); X tmps = spat->spat_regexp->subbase = nsavestr(t,strend-t); X spat->spat_regexp->subend = tmps + (strend-t); X tmps = spat->spat_regexp->startp[0] = tmps + (s - t); X spat->spat_regexp->endp[0] = tmps + spat->spat_short->str_cur; X curspat = spat; X } X str_sset(str,&str_yes); X STABSET(str); X st[++sp] = str; X return sp; X Xnope: X ++spat->spat_short->str_u.str_useful; X if (gimme == G_ARRAY) X return sp; X str_sset(str,&str_no); X STABSET(str); X st[++sp] = str; X return sp; X} X X#ifdef BUGGY_MSC X #pragma intrinsic(memcmp) X#endif /* BUGGY_MSC */ X Xint Xdo_split(str,spat,limit,gimme,arglast) XSTR *str; Xregister SPAT *spat; Xregister int limit; Xint gimme; Xint *arglast; X{ X register ARRAY *ary = stack; X STR **st = ary->ary_array; X register int sp = arglast[0] + 1; X register char *s = str_get(st[sp]); X char *strend = s + st[sp--]->str_cur; X register STR *dstr; X register char *m; X int iters = 0; X int maxiters = (strend - s) + 10; X int i; X char *orig; X int origlimit = limit; X int realarray = 0; X X if (!spat || !s) X fatal("panic: do_split"); X else if (spat->spat_runtime) { X nointrp = "|)"; X sp = eval(spat->spat_runtime,G_SCALAR,sp); X st = stack->ary_array; X m = str_get(dstr = st[sp--]); X nointrp = ""; X if (*m == ' ' && dstr->str_cur == 1) { X str_set(dstr,"\\s+"); X m = dstr->str_ptr; X spat->spat_flags |= SPAT_SKIPWHITE; X } X if (spat->spat_regexp) { X regfree(spat->spat_regexp); X spat->spat_regexp = Null(REGEXP*); /* avoid possible double free */ X } X spat->spat_regexp = regcomp(m,m+dstr->str_cur, X spat->spat_flags & SPAT_FOLD); X if (spat->spat_flags & SPAT_KEEP || X (spat->spat_runtime->arg_type == O_ITEM && X (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) { X arg_free(spat->spat_runtime); /* it won't change, so */ X spat->spat_runtime = Nullarg; /* no point compiling again */ X } X } X#ifdef DEBUGGING X if (debug & 8) { X deb("2.SPAT /%s/\n",spat->spat_regexp->precomp); X } X#endif X ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab); X if (ary && (gimme != G_ARRAY || (spat->spat_flags & SPAT_ONCE))) { X realarray = 1; X if (!(ary->ary_flags & ARF_REAL)) { X ary->ary_flags |= ARF_REAL; X for (i = ary->ary_fill; i >= 0; i--) X ary->ary_array[i] = Nullstr; /* don't free mere refs */ X } X ary->ary_fill = -1; X sp = -1; /* temporarily switch stacks */ X } X else X ary = stack; X orig = s; X if (spat->spat_flags & SPAT_SKIPWHITE) { X while (isascii(*s) && isspace(*s)) X s++; X } X if (!limit) X limit = maxiters + 2; X if (strEQ("\\s+",spat->spat_regexp->precomp)) { X while (--limit) { X for (m = s; m < strend && !(isascii(*m)&&isspace(*m)); m++) ; X if (m >= strend) X break; X dstr = Str_new(30,m-s); X str_nset(dstr,s,m-s); X if (!realarray) X str_2mortal(dstr); X (void)astore(ary, ++sp, dstr); X for (s = m + 1; s < strend && isascii(*s) && isspace(*s); s++) ; X } X } X else if (strEQ("^",spat->spat_regexp->precomp)) { X while (--limit) { X for (m = s; m < strend && *m != '\n'; m++) ; X m++; X if (m >= strend) X break; X dstr = Str_new(30,m-s); X str_nset(dstr,s,m-s); X if (!realarray) X str_2mortal(dstr); X (void)astore(ary, ++sp, dstr); X s = m; X } X } X else if (spat->spat_short) { X i = spat->spat_short->str_cur; X if (i == 1) { X int fold = (spat->spat_flags & SPAT_FOLD); X X i = *spat->spat_short->str_ptr; X if (fold && isupper(i)) X i = tolower(i); X while (--limit) { X if (fold) { X for ( m = s; X m < strend && *m != i && X (!isupper(*m) || tolower(*m) != i); X m++) X ; X } X else X for (m = s; m < strend && *m != i; m++) ; X if (m >= strend) X break; X dstr = Str_new(30,m-s); X str_nset(dstr,s,m-s); X if (!realarray) X str_2mortal(dstr); X (void)astore(ary, ++sp, dstr); X s = m + 1; X } X } X else { X#ifndef lint X while (s < strend && --limit && X (m=fbminstr((unsigned char*)s, (unsigned char*)strend, X spat->spat_short)) ) X#endif X { X dstr = Str_new(31,m-s); X str_nset(dstr,s,m-s); X if (!realarray) X str_2mortal(dstr); X (void)astore(ary, ++sp, dstr); X s = m + i; X } X } X } X else { X maxiters += (strend - s) * spat->spat_regexp->nparens; X while (s < strend && --limit && X regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) { X if (spat->spat_regexp->subbase X && spat->spat_regexp->subbase != orig) { X m = s; X s = orig; X orig = spat->spat_regexp->subbase; X s = orig + (m - s); X strend = s + (strend - m); X } X m = spat->spat_regexp->startp[0]; X dstr = Str_new(32,m-s); X str_nset(dstr,s,m-s); X if (!realarray) X str_2mortal(dstr); X (void)astore(ary, ++sp, dstr); X if (spat->spat_regexp->nparens) { X for (i = 1; i <= spat->spat_regexp->nparens; i++) { X s = spat->spat_regexp->startp[i]; X m = spat->spat_regexp->endp[i]; X dstr = Str_new(33,m-s); X str_nset(dstr,s,m-s); X if (!realarray) X str_2mortal(dstr); X (void)astore(ary, ++sp, dstr); X } X } X s = spat->spat_regexp->endp[0]; X } X } X if (realarray) X iters = sp + 1; X else X iters = sp - arglast[0]; X if (iters > maxiters) X fatal("Split loop"); X if (s < strend || origlimit) { /* keep field after final delim? */ X dstr = Str_new(34,strend-s); X str_nset(dstr,s,strend-s); X if (!realarray) X str_2mortal(dstr); X (void)astore(ary, ++sp, dstr); X iters++; X } X else { X#ifndef I286x X while (iters > 0 && ary->ary_array[sp]->str_cur == 0) X iters--,sp--; X#else X char *zaps; X int zapb; X X if (iters > 0) { X zaps = str_get(afetch(ary,sp,FALSE)); X zapb = (int) *zaps; X } X X while (iters > 0 && (!zapb)) { X iters--,sp--; X if (iters > 0) { X zaps = str_get(afetch(ary,iters-1,FALSE)); X zapb = (int) *zaps; X } X } X#endif X } X if (realarray) { X ary->ary_fill = sp; X if (gimme == G_ARRAY) { X sp++; X astore(stack, arglast[0] + 1 + sp, Nullstr); X Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*); X return arglast[0] + sp; X } X } X else { X if (gimme == G_ARRAY) X return sp; X } X sp = arglast[0] + 1; X str_numset(str,(double)iters); X STABSET(str); X st[sp] = str; X return sp; X} X Xint Xdo_unpack(str,gimme,arglast) XSTR *str; Xint gimme; Xint *arglast; X{ X STR **st = stack->ary_array; X register int sp = arglast[0] + 1; X register char *pat = str_get(st[sp++]); X register char *s = str_get(st[sp]); X char *strend = s + st[sp--]->str_cur; X char *strbeg = s; X register char *patend = pat + st[sp]->str_cur; X int datumtype; X register int len; X register int bits; X X /* These must not be in registers: */ X short ashort; X int aint; X long along; X unsigned short aushort; X unsigned int auint; X unsigned long aulong; X char *aptr; X float afloat; X double adouble; X int checksum = 0; X unsigned long culong; X double cdouble; X X if (gimme != G_ARRAY) { /* arrange to do first one only */ X for (patend = pat; !isalpha(*patend); patend++); X if (index("aAbBhH", *patend) || *pat == '%') { X patend++; X while (isdigit(*patend) || *patend == '*') X patend++; X } X else X patend++; X } X sp--; X while (pat < patend) { X reparse: X datumtype = *pat++; X if (pat >= patend) X len = 1; X else if (*pat == '*') { X len = strend - strbeg; /* long enough */ X pat++; X } X else if (isdigit(*pat)) { X len = *pat++ - '0'; X while (isdigit(*pat)) X len = (len * 10) + (*pat++ - '0'); X } X else X len = (datumtype != '@'); X switch(datumtype) { X default: X break; X case '%': X if (len == 1 && pat[-1] != '1') X len = 16; X checksum = len; X culong = 0; X cdouble = 0; X if (pat < patend) X goto reparse; X break; X case '@': X if (len > strend - s) X fatal("@ outside of string"); X s = strbeg + len; X break; X case 'X': X if (len > s - strbeg) X fatal("X outside of string"); X s -= len; X break; X case 'x': X if (len > strend - s) X fatal("x outside of string"); X s += len; X break; X case 'A': X case 'a': X if (len > strend - s) X len = strend - s; X if (checksum) X goto uchar_checksum; X str = Str_new(35,len); X str_nset(str,s,len); X s += len; X if (datumtype == 'A') { X aptr = s; /* borrow register */ X s = str->str_ptr + len - 1; X while (s >= str->str_ptr && (!*s || (isascii(*s)&&isspace(*s)))) X s--; X *++s = '\0'; X str->str_cur = s - str->str_ptr; X s = aptr; /* unborrow register */ X } X (void)astore(stack, ++sp, str_2mortal(str)); X break; X case 'B': X case 'b': X if (pat[-1] == '*' || len > (strend - s) * 8) X len = (strend - s) * 8; X str = Str_new(35, len + 1); X str->str_cur = len; X str->str_pok = 1; X aptr = pat; /* borrow register */ X pat = str->str_ptr; X if (datumtype == 'b') { X aint = len; X for (len = 0; len < aint; len++) { X if (len & 7) X bits >>= 1; X else X bits = *s++; X *pat++ = '0' + (bits & 1); X } X } X else { X aint = len; X for (len = 0; len < aint; len++) { X if (len & 7) X bits <<= 1; X else X bits = *s++; X *pat++ = '0' + ((bits & 128) != 0); X } X } X *pat = '\0'; X pat = aptr; /* unborrow register */ X (void)astore(stack, ++sp, str_2mortal(str)); X break; X case 'H': X case 'h': X if (pat[-1] == '*' || len > (strend - s) * 2) X len = (strend - s) * 2; X str = Str_new(35, len + 1); X str->str_cur = len; X str->str_pok = 1; X aptr = pat; /* borrow register */ X pat = str->str_ptr; X if (datumtype == 'h') { X aint = len; X for (len = 0; len < aint; len++) { X if (len & 1) X bits >>= 4; X else X bits = *s++; X *pat++ = hexdigit[bits & 15]; X } X } X else { X aint = len; X for (len = 0; len < aint; len++) { X if (len & 1) X bits <<= 4; X else X bits = *s++; X *pat++ = hexdigit[(bits >> 4) & 15]; X } X } X *pat = '\0'; X pat = aptr; /* unborrow register */ X (void)astore(stack, ++sp, str_2mortal(str)); X break; X case 'c': X if (len > strend - s) X len = strend - s; X if (checksum) { X while (len-- > 0) { X aint = *s++; X if (aint >= 128) /* fake up signed chars */ X aint -= 256; X culong += aint; X } X } X else { X while (len-- > 0) { X aint = *s++; X if (aint >= 128) /* fake up signed chars */ X aint -= 256; X str = Str_new(36,0); X str_numset(str,(double)aint); X (void)astore(stack, ++sp, str_2mortal(str)); X } X } X break; X case 'C': X if (len > strend - s) X len = strend - s; X if (checksum) { X uchar_checksum: X while (len-- > 0) { X auint = *s++ & 255; X culong += auint; X } X } X else { X while (len-- > 0) { X auint = *s++ & 255; X str = Str_new(37,0); X str_numset(str,(double)auint); X (void)astore(stack, ++sp, str_2mortal(str)); X } X } X break; X case 's': X along = (strend - s) / sizeof(short); X if (len > along) X len = along; X if (checksum) { X while (len-- > 0) { X bcopy(s,(char*)&ashort,sizeof(short)); X s += sizeof(short); X culong += ashort; X } X } X else { X while (len-- > 0) { X bcopy(s,(char*)&ashort,sizeof(short)); X s += sizeof(short); X str = Str_new(38,0); X str_numset(str,(double)ashort); X (void)astore(stack, ++sp, str_2mortal(str)); X } X } X break; X case 'n': X case 'S': X along = (strend - s) / sizeof(unsigned short); X if (len > along) X len = along; X if (checksum) { X while (len-- > 0) { X bcopy(s,(char*)&aushort,sizeof(unsigned short)); X s += sizeof(unsigned short); X#ifdef HAS_NTOHS X if (datumtype == 'n') X aushort = ntohs(aushort); X#endif X culong += aushort; X } X } X else { X while (len-- > 0) { X bcopy(s,(char*)&aushort,sizeof(unsigned short)); X s += sizeof(unsigned short); X str = Str_new(39,0); X#ifdef HAS_NTOHS X if (datumtype == 'n') X aushort = ntohs(aushort); X#endif X str_numset(str,(double)aushort); X (void)astore(stack, ++sp, str_2mortal(str)); X } X } X break; X case 'i': X along = (strend - s) / sizeof(int); X if (len > along) X len = along; X if (checksum) { X while (len-- > 0) { X bcopy(s,(char*)&aint,sizeof(int)); X s += sizeof(int); X if (checksum > 32) X cdouble += (double)aint; X else X culong += aint; X } X } X else { X while (len-- > 0) { X bcopy(s,(char*)&aint,sizeof(int)); X s += sizeof(int); X str = Str_new(40,0); X str_numset(str,(double)aint); X (void)astore(stack, ++sp, str_2mortal(str)); X } X } X break; X case 'I': X along = (strend - s) / sizeof(unsigned int); X if (len > along) X len = along; X if (checksum) { X while (len-- > 0) { X bcopy(s,(char*)&auint,sizeof(unsigned int)); X s += sizeof(unsigned int); X if (checksum > 32) X cdouble += (double)auint; X else X culong += auint; X } X } X else { X while (len-- > 0) { X bcopy(s,(char*)&auint,sizeof(unsigned int)); X s += sizeof(unsigned int); X str = Str_new(41,0); X str_numset(str,(double)auint); X (void)astore(stack, ++sp, str_2mortal(str)); X } X } X break; X case 'l': X along = (strend - s) / sizeof(long); X if (len > along) X len = along; X if (checksum) { X while (len-- > 0) { X bcopy(s,(char*)&along,sizeof(long)); X s += sizeof(long); X if (checksum > 32) X cdouble += (double)along; X else X culong += along; X } X } X else { X while (len-- > 0) { X bcopy(s,(char*)&along,sizeof(long)); X s += sizeof(long); X str = Str_new(42,0); X str_numset(str,(double)along); X (void)astore(stack, ++sp, str_2mortal(str)); X } X } X break; X case 'N': X case 'L': X along = (strend - s) / sizeof(unsigned long); X if (len > along) X len = along; X if (checksum) { X while (len-- > 0) { X bcopy(s,(char*)&aulong,sizeof(unsigned long)); X s += sizeof(unsigned long); X#ifdef HAS_NTOHL X if (datumtype == 'N') X aulong = ntohl(aulong); X#endif X if (checksum > 32) X cdouble += (double)aulong; X else X culong += aulong; X } X } X else { X while (len-- > 0) { X bcopy(s,(char*)&aulong,sizeof(unsigned long)); X s += sizeof(unsigned long); X str = Str_new(43,0); X#ifdef HAS_NTOHL X if (datumtype == 'N') X aulong = ntohl(aulong); X#endif X str_numset(str,(double)aulong); X (void)astore(stack, ++sp, str_2mortal(str)); X } X } X break; X case 'p': X along = (strend - s) / sizeof(char*); X if (len > along) X len = along; X while (len-- > 0) { X if (sizeof(char*) > strend - s) X break; X else { X bcopy(s,(char*)&aptr,sizeof(char*)); X s += sizeof(char*); X } X str = Str_new(44,0); X if (aptr) X str_set(str,aptr); X (void)astore(stack, ++sp, str_2mortal(str)); X } X break; X /* float and double added gnb@melba.bby.oz.au 22/11/89 */ X case 'f': X case 'F': X along = (strend - s) / sizeof(float); X if (len > along) X len = along; X if (checksum) { X while (len-- > 0) { X bcopy(s, (char *)&afloat, sizeof(float)); X s += sizeof(float); X cdouble += afloat; X } X } X else { X while (len-- > 0) { X bcopy(s, (char *)&afloat, sizeof(float)); X s += sizeof(float); X str = Str_new(47, 0); X str_numset(str, (double)afloat); X (void)astore(stack, ++sp, str_2mortal(str)); X } X } X break; X case 'd': X case 'D': X along = (strend - s) / sizeof(double); X if (len > along) X len = along; X if (checksum) { X while (len-- > 0) { X bcopy(s, (char *)&adouble, sizeof(double)); X s += sizeof(double); X cdouble += adouble; X } X } X else { X while (len-- > 0) { X bcopy(s, (char *)&adouble, sizeof(double)); X s += sizeof(double); X str = Str_new(48, 0); X str_numset(str, (double)adouble); X (void)astore(stack, ++sp, str_2mortal(str)); X } X } X break; X case 'u': X along = (strend - s) * 3 / 4; X str = Str_new(42,along); X while (s < strend && *s > ' ' && *s < 'a') { X int a,b,c,d; X char hunk[4]; X X hunk[3] = '\0'; X len = (*s++ - ' ') & 077; X while (len > 0) { X if (s < strend && *s >= ' ') X a = (*s++ - ' ') & 077; X else X a = 0; X if (s < strend && *s >= ' ') X b = (*s++ - ' ') & 077; X else X b = 0; X if (s < strend && *s >= ' ') X c = (*s++ - ' ') & 077; X else X c = 0; X if (s < strend && *s >= ' ') X d = (*s++ - ' ') & 077; X else X d = 0; X hunk[0] = a << 2 | b >> 4; X hunk[1] = b << 4 | c >> 2; X hunk[2] = c << 6 | d; X str_ncat(str,hunk, len > 3 ? 3 : len); X len -= 3; X } X if (*s == '\n') X s++; X else if (s[1] == '\n') /* possible checksum byte */ X s += 2; X } X (void)astore(stack, ++sp, str_2mortal(str)); X break; X } X if (checksum) { X str = Str_new(42,0); X if (index("fFdD", datumtype) || X (checksum > 32 && index("iIlLN", datumtype)) ) { X double modf(); X double trouble; X X adouble = 1.0; X while (checksum >= 16) { X checksum -= 16; X adouble *= 65536.0; X } X while (checksum >= 4) { X checksum -= 4; X adouble *= 16.0; X } X while (checksum--) X adouble *= 2.0; X along = (1 << checksum) - 1; X while (cdouble < 0.0) X cdouble += adouble; X cdouble = modf(cdouble / adouble, &trouble) * adouble; X str_numset(str,cdouble); X } X else { X if (checksum < 32) { X along = (1 << checksum) - 1; X culong &= (unsigned long)along; X } X str_numset(str,(double)culong); X } X (void)astore(stack, ++sp, str_2mortal(str)); X checksum = 0; X } X } X return sp; X} X Xint Xdo_slice(stab,str,numarray,lval,gimme,arglast) XSTAB *stab; XSTR *str; Xint numarray; Xint lval; Xint gimme; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[1]; X register int max = arglast[2]; X register char *tmps; X register int len; X register int magic = 0; X register ARRAY *ary; X register HASH *hash; X int oldarybase = arybase; X X if (numarray) { X if (numarray == 2) { /* a slice of a LIST */ X ary = stack; X ary->ary_fill = arglast[3]; X arybase -= max + 1; X st[sp] = str; /* make stack size available */ X str_numset(str,(double)(sp - 1)); X } X else X ary = stab_array(stab); /* a slice of an array */ X } X else { X if (lval) { X if (stab == envstab) X magic = 'E'; X else if (stab == sigstab) X magic = 'S'; X#ifdef SOME_DBM X else if (stab_hash(stab)->tbl_dbm) X magic = 'D'; X#endif /* SOME_DBM */ X } X hash = stab_hash(stab); /* a slice of an associative array */ X } X X if (gimme == G_ARRAY) { X if (numarray) { X while (sp < max) { X if (st[++sp]) { X st[sp-1] = afetch(ary, X ((int)str_gnum(st[sp])) - arybase, lval); X } X else X st[sp-1] = &str_undef; X } X } X else { X while (sp < max) { X if (st[++sp]) { X tmps = str_get(st[sp]); X len = st[sp]->str_cur; X st[sp-1] = hfetch(hash,tmps,len, lval); X if (magic) X str_magic(st[sp-1],stab,magic,tmps,len); X } X else X st[sp-1] = &str_undef; X } X } X sp--; X } X else { X if (numarray) { X if (st[max]) X st[sp] = afetch(ary, X ((int)str_gnum(st[max])) - arybase, lval); X else X st[sp] = &str_undef; X } X else { X if (st[max]) { X tmps = str_get(st[max]); X len = st[max]->str_cur; X st[sp] = hfetch(hash,tmps,len, lval); X if (magic) X str_magic(st[sp],stab,magic,tmps,len); X } X else X st[sp] = &str_undef; X } X } X arybase = oldarybase; X return sp; X} X Xint Xdo_splice(ary,gimme,arglast) Xregister ARRAY *ary; Xint gimme; Xint *arglast; X{ X register STR **st = stack->ary_array; X register int sp = arglast[1]; X int max = arglast[2] + 1; X register STR **src; X register STR **dst; X register int i; X register int offset; X register int length; X int newlen; X int after; X int diff; X STR **tmparyval; X X if (++sp < max) { X offset = ((int)str_gnum(st[sp])) - arybase; X if (offset < 0) X offset += ary->ary_fill + 1; X if (++sp < max) { X length = (int)str_gnum(st[sp++]); X if (length < 0) X length = 0; X } X else X length = ary->ary_max; /* close enough to infinity */ X } X else { X offset = 0; X length = ary->ary_max; X } X if (offset < 0) { X length += offset; X offset = 0; X if (length < 0) X length = 0; X } X if (offset > ary->ary_fill + 1) X offset = ary->ary_fill + 1; X after = ary->ary_fill + 1 - (offset + length); X if (after < 0) { /* not that much array */ X length += after; /* offset+length now in array */ X after = 0; X if (!ary->ary_alloc) { X afill(ary,0); X afill(ary,-1); X } X } X X /* At this point, sp .. max-1 is our new LIST */ X X newlen = max - sp; X diff = newlen - length; X X if (diff < 0) { /* shrinking the area */ X if (newlen) { X New(451, tmparyval, newlen, STR*); /* so remember insertion */ X Copy(st+sp, tmparyval, newlen, STR*); X } X X sp = arglast[0] + 1; X if (gimme == G_ARRAY) { /* copy return vals to stack */ X if (sp + length >= stack->ary_max) { X astore(stack,sp + length, Nullstr); X st = stack->ary_array; X } X Copy(ary->ary_array+offset, st+sp, length, STR*); X if (ary->ary_flags & ARF_REAL) { X for (i = length, dst = st+sp; i; i--) X str_2mortal(*dst++); /* free them eventualy */ X } X sp += length - 1; X } X else { X st[sp] = ary->ary_array[offset+length-1]; X if (ary->ary_flags & ARF_REAL) X str_2mortal(st[sp]); X } X ary->ary_fill += diff; X X /* pull up or down? */ X X if (offset < after) { /* easier to pull up */ X if (offset) { /* esp. if nothing to pull */ X src = &ary->ary_array[offset-1]; X dst = src - diff; /* diff is negative */ X for (i = offset; i > 0; i--) /* can't trust Copy */ X *dst-- = *src--; X } X Zero(ary->ary_array, -diff, STR*); X ary->ary_array -= diff; /* diff is negative */ X ary->ary_max += diff; X } X else { X if (after) { /* anything to pull down? */ X src = ary->ary_array + offset + length; X dst = src + diff; /* diff is negative */ X Copy(src, dst, after, STR*); X } X Zero(&ary->ary_array[ary->ary_fill+1], -diff, STR*); X /* avoid later double free */ X } X if (newlen) { X for (src = tmparyval, dst = ary->ary_array + offset; X newlen; newlen--) { X *dst = Str_new(46,0); X str_sset(*dst++,*src++); X } X Safefree(tmparyval); X } X } X else { /* no, expanding (or same) */ X if (length) { X New(452, tmparyval, length, STR*); /* so remember deletion */ X Copy(ary->ary_array+offset, tmparyval, length, STR*); X } X X if (diff > 0) { /* expanding */ X X /* push up or down? */ X X if (offset < after && diff <= ary->ary_array - ary->ary_alloc) { X if (offset) { X src = ary->ary_array; X dst = src - diff; X Copy(src, dst, offset, STR*); X } X ary->ary_array -= diff; /* diff is positive */ X ary->ary_max += diff; X ary->ary_fill += diff; X } X else { X if (ary->ary_fill + diff >= ary->ary_max) /* oh, well */ X astore(ary, ary->ary_fill + diff, Nullstr); X else X ary->ary_fill += diff; X if (after) { X dst = ary->ary_array + ary->ary_fill; X src = dst - diff; X for (i = after; i; i--) { X if (*dst) /* str was hanging around */ X str_free(*dst); /* after $#foo */ X *dst-- = *src; X *src-- = Nullstr; X } X } X } X } X X for (src = st+sp, dst = ary->ary_array + offset; newlen; newlen--) { X *dst = Str_new(46,0); X str_sset(*dst++,*src++); X } X sp = arglast[0] + 1; X if (gimme == G_ARRAY) { /* copy return vals to stack */ X if (length) { X Copy(tmparyval, st+sp, length, STR*); X if (ary->ary_flags & ARF_REAL) { X for (i = length, dst = st+sp; i; i--) X str_2mortal(*dst++); /* free them eventualy */ X } X Safefree(tmparyval); X } X sp += length - 1; X } X else if (length) { X st[sp] = tmparyval[length-1]; X if (ary->ary_flags & ARF_REAL) X str_2mortal(st[sp]); X Safefree(tmparyval); X } X else X st[sp] = &str_undef; X } X return sp; X} X Xint Xdo_grep(arg,str,gimme,arglast) Xregister ARG *arg; XSTR *str; Xint gimme; Xint *arglast; X{ X STR **st = stack->ary_array; X register int dst = arglast[1]; X register int src = dst + 1; X register int sp = arglast[2]; X register int i = sp - arglast[1]; X int oldsave = savestack->ary_fill; X SPAT *oldspat = curspat; X int oldtmps_base = tmps_base; X X savesptr(&stab_val(defstab)); X tmps_base = tmps_max; X if ((arg[1].arg_type & A_MASK) != A_EXPR) { X arg[1].arg_type &= A_MASK; X dehoist(arg,1); X arg[1].arg_type |= A_DONT; X } X arg = arg[1].arg_ptr.arg_arg; X while (i-- > 0) { X if (st[src]) X stab_val(defstab) = st[src]; X else X stab_val(defstab) = str_mortal(&str_undef); X (void)eval(arg,G_SCALAR,sp); X st = stack->ary_array; X if (str_true(st[sp+1])) X st[dst++] = st[src]; X src++; X curspat = oldspat; X } X restorelist(oldsave); X tmps_base = oldtmps_base; X if (gimme != G_ARRAY) { X str_numset(str,(double)(dst - arglast[1])); X STABSET(str); X st[arglast[0]+1] = str; X return arglast[0]+1; X } X return arglast[0] + (dst - arglast[1]); X} X Xint Xdo_reverse(arglast) Xint *arglast; X{ X STR **st = stack->ary_array; X register STR **up = &st[arglast[1]]; X register STR **down = &st[arglast[2]]; X register int i = arglast[2] - arglast[1]; X X while (i-- > 0) { X *up++ = *down; X if (i-- > 0) X *down-- = *up; X } X i = arglast[2] - arglast[1]; X Copy(down+1,up,i/2,STR*); X return arglast[2] - 1; X} X Xint Xdo_sreverse(str,arglast) XSTR *str; Xint *arglast; X{ X STR **st = stack->ary_array; X register char *up; X register char *down; X register int tmp; X X str_sset(str,st[arglast[2]]); X up = str_get(str); X if (str->str_cur > 1) { X down = str->str_ptr + str->str_cur - 1; X while (down > up) { X tmp = *up; X *up++ = *down; X *down-- = tmp; X } X } X STABSET(str); X st[arglast[0]+1] = str; X return arglast[0]+1; X} X Xstatic CMD *sortcmd; Xstatic HASH *sortstash = Null(HASH*); Xstatic STAB *firststab = Nullstab; Xstatic STAB *secondstab = Nullstab; X Xint Xdo_sort(str,stab,gimme,arglast) XSTR *str; XSTAB *stab; Xint gimme; Xint *arglast; X{ X register STR **st = stack->ary_array; X int sp = arglast[1]; X register STR **up; X register int max = arglast[2] - sp; X register int i; X int sortcmp(); X int sortsub(); X STR *oldfirst; X STR *oldsecond; X ARRAY *oldstack; X static ARRAY *sortstack = Null(ARRAY*); X X if (gimme != G_ARRAY) { X str_sset(str,&str_undef); X STABSET(str); X st[sp] = str; X return sp; X } X up = &st[sp]; X st += sp; /* temporarily make st point to args */ X for (i = 1; i <= max; i++) { X if (*up = st[i]) { X if (!(*up)->str_pok) X (void)str_2ptr(*up); X else X (*up)->str_pok &= ~SP_TEMP; X up++; X } X } X st -= sp; X max = up - &st[sp]; X sp--; X if (max > 1) { X if (stab) { X int oldtmps_base = tmps_base; X X if (!stab_sub(stab) || !(sortcmd = stab_sub(stab)->cmd)) X fatal("Undefined subroutine \"%s\" in sort", stab_name(stab)); X if (!sortstack) { X sortstack = anew(Nullstab); X astore(sortstack, 0, Nullstr); X aclear(sortstack); X sortstack->ary_flags = 0; X } X oldstack = stack; X stack = sortstack; X tmps_base = tmps_max; X if (sortstash != stab_stash(stab)) { X firststab = stabent("a",TRUE); X secondstab = stabent("b",TRUE); X sortstash = stab_stash(stab); X } X oldfirst = stab_val(firststab); X oldsecond = stab_val(secondstab); X#ifndef lint X qsort((char*)(st+sp+1),max,sizeof(STR*),sortsub); X#else X qsort(Nullch,max,sizeof(STR*),sortsub); X#endif X stab_val(firststab) = oldfirst; X stab_val(secondstab) = oldsecond; X tmps_base = oldtmps_base; X stack = oldstack; X } X#ifndef lint X else X qsort((char*)(st+sp+1),max,sizeof(STR*),sortcmp); X#endif X } X return sp+max; X} X Xint Xsortsub(str1,str2) XSTR **str1; XSTR **str2; X{ X stab_val(firststab) = *str1; X stab_val(secondstab) = *str2; X cmd_exec(sortcmd,G_SCALAR,-1); X return (int)str_gnum(*stack->ary_array); X} X Xsortcmp(strp1,strp2) XSTR **strp1; XSTR **strp2; X{ X register STR *str1 = *strp1; X register STR *str2 = *strp2; X int retval; X X if (str1->str_cur < str2->str_cur) { X if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur)) X return retval; X else X return -1; X } X else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur)) X return retval; X else if (str1->str_cur == str2->str_cur) X return 0; X else X return 1; X} X Xint Xdo_range(gimme,arglast) Xint gimme; Xint *arglast; X{ X STR **st = stack->ary_array; X register int sp = arglast[0]; X register int i; X register ARRAY *ary = stack; X register STR *str; X int max; X X if (gimme != G_ARRAY) X fatal("panic: do_range"); X X if (st[sp+1]->str_nok || !st[sp+1]->str_pok || X (looks_like_number(st[sp+1]) && *st[sp+1]->str_ptr != '0') ) { X i = (int)str_gnum(st[sp+1]); X max = (int)str_gnum(st[sp+2]); X while (i <= max) { X (void)astore(ary, ++sp, str = str_mortal(&str_no)); X str_numset(str,(double)i++); X } X } X else { X STR *final = str_mortal(st[sp+2]); X char *tmps = str_get(final); X X str = str_mortal(st[sp+1]); X while (!str->str_nok && str->str_cur <= final->str_cur && X strNE(str->str_ptr,tmps) ) { X (void)astore(ary, ++sp, str); X str = str_2mortal(str_smake(str)); X str_inc(str); X } X if (strEQ(str->str_ptr,tmps)) X (void)astore(ary, ++sp, str); X } X return sp; X} X Xint Xdo_repeatary(arglast) Xint *arglast; X{ X STR **st = stack->ary_array; X register int sp = arglast[0]; X register int items = arglast[1] - sp; X register int count = (int) str_gnum(st[arglast[2]]); X register ARRAY *ary = stack; X register int i; X int max; X X max = items * count; X if (max > 0 && sp + max > stack->ary_max) { X astore(stack, sp + max, Nullstr); X st = stack->ary_array; X } X if (count > 1) { X for (i = arglast[1]; i > sp; i--) X st[i]->str_pok &= ~SP_TEMP; X repeatcpy((char*)&st[arglast[1]+1], (char*)&st[sp+1], X items * sizeof(STR*), count); X } X sp += max; X X return sp; X} X Xint Xdo_caller(arg,maxarg,gimme,arglast) XARG *arg; Xint maxarg; Xint gimme; Xint *arglast; X{ X STR **st = stack->ary_array; X register int sp = arglast[0]; X register CSV *csv = curcsv; X STR *str; X int count = 0; X X if (!csv) X fatal("There is no caller"); X if (maxarg) X count = (int) str_gnum(st[sp+1]); X for (;;) { X if (!csv) X return sp; X if (DBsub && csv->curcsv && csv->curcsv->sub == stab_sub(DBsub)) X count++; X if (!count--) X break; X csv = csv->curcsv; X } X if (gimme != G_ARRAY) { X STR *str = arg->arg_ptr.arg_str; X str_set(str,csv->curcmd->c_stash->tbl_name); X STABSET(str); X st[++sp] = str; X return sp; X } X X#ifndef lint X (void)astore(stack,++sp, X str_2mortal(str_make(csv->curcmd->c_stash->tbl_name,0)) ); X (void)astore(stack,++sp, X str_2mortal(str_make(stab_val(csv->curcmd->c_filestab)->str_ptr,0)) ); X (void)astore(stack,++sp, X str_2mortal(str_nmake((double)csv->curcmd->c_line)) ); X if (!maxarg) X return sp; X str = Str_new(49,0); X stab_fullname(str, csv->stab); X (void)astore(stack,++sp, str_2mortal(str)); X (void)astore(stack,++sp, X str_2mortal(str_nmake((double)csv->hasargs)) ); X (void)astore(stack,++sp, X str_2mortal(str_nmake((double)csv->wantarray)) ); X if (csv->hasargs) { X ARRAY *ary = csv->argarray; X X if (dbargs->ary_max < ary->ary_fill) X astore(dbargs,ary->ary_fill,Nullstr); X Copy(ary->ary_array, dbargs->ary_array, ary->ary_fill+1, STR*); X dbargs->ary_fill = ary->ary_fill; X } X#else X (void)astore(stack,++sp, X str_2mortal(str_make("",0))); X#endif X return sp; X} X Xint Xdo_tms(str,gimme,arglast) XSTR *str; Xint gimme; Xint *arglast; X{ X#ifdef MSDOS X return -1; X#else X STR **st = stack->ary_array; X register int sp = arglast[0]; X X if (gimme != G_ARRAY) { X str_sset(str,&str_undef); X STABSET(str); X st[++sp] = str; X return sp; X } X (void)times(×buf); X X#ifndef HZ X#define HZ 60 X#endif X X#ifndef lint X (void)astore(stack,++sp, X str_2mortal(str_nmake(((double)timesbuf.tms_utime)/HZ))); X (void)astore(stack,++sp, X str_2mortal(str_nmake(((double)timesbuf.tms_stime)/HZ))); X (void)astore(stack,++sp, X str_2mortal(str_nmake(((double)timesbuf.tms_cutime)/HZ))); X (void)astore(stack,++sp, X str_2mortal(str_nmake(((double)timesbuf.tms_cstime)/HZ))); X#else X (void)astore(stack,++sp, X str_2mortal(str_nmake(0.0))); X#endif X return sp; X#endif X} X Xint Xdo_time(str,tmbuf,gimme,arglast) XSTR *str; Xstruct tm *tmbuf; Xint gimme; Xint *arglast; X{ X register ARRAY *ary = stack; X STR **st = ary->ary_array; X register int sp = arglast[0]; X X if (!tmbuf || gimme != G_ARRAY) { X str_sset(str,&str_undef); X STABSET(str); X st[++sp] = str; X return sp; X } X (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_sec))); X (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_min))); X (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_hour))); X (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_mday))); X (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_mon))); X (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_year))); X (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_wday))); X (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_yday))); X (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_isdst))); X return sp; X} X Xint Xdo_kv(str,hash,kv,gimme,arglast) XSTR *str; XHASH *hash; Xint kv; Xint gimme; Xint *arglast; X{ X register ARRAY *ary = stack; X STR **st = ary->ary_array; X register int sp = arglast[0]; X int i; X register HENT *entry; X char *tmps; X STR *tmpstr; X int dokeys = (kv == O_KEYS || kv == O_HASH); X int dovalues = (kv == O_VALUES || kv == O_HASH); X X if (gimme != G_ARRAY) { X str_sset(str,&str_undef); X STABSET(str); X st[++sp] = str; X return sp; X } X (void)hiterinit(hash); X while (entry = hiternext(hash)) { X if (dokeys) { X tmps = hiterkey(entry,&i); X if (!i) X tmps = ""; X (void)astore(ary,++sp,str_2mortal(str_make(tmps,i))); X } X if (dovalues) { X tmpstr = Str_new(45,0); X#ifdef DEBUGGING X if (debug & 8192) { X sprintf(buf,"%d%%%d=%d\n",entry->hent_hash, X hash->tbl_max+1,entry->hent_hash & hash->tbl_max); X str_set(tmpstr,buf); X } X else X#endif X str_sset(tmpstr,hiterval(hash,entry)); X (void)astore(ary,++sp,str_2mortal(tmpstr)); X } X } X return sp; X} X Xint Xdo_each(str,hash,gimme,arglast) XSTR *str; XHASH *hash; Xint gimme; Xint *arglast; X{ X STR **st = stack->ary_array; X register int sp = arglast[0]; X static STR *mystrk = Nullstr; X HENT *entry = hiternext(hash); X int i; X char *tmps; X X if (mystrk) { X str_free(mystrk); X mystrk = Nullstr; X } X X if (entry) { X if (gimme == G_ARRAY) { X tmps = hiterkey(entry, &i); X if (!i) X tmps = ""; X st[++sp] = mystrk = str_make(tmps,i); X } X st[++sp] = str; X str_sset(str,hiterval(hash,entry)); X STABSET(str); X return sp; X } X else X return sp; X} !STUFFY!FUNK! echo Extracting h2ph.SH sed >h2ph.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 fi 2>/dev/null X . ./config.sh X ;; Xesac X: This forces SH files to create target in same directory as SH file. X: This is so that make depend always knows where to find SH derivatives. Xcase "$0" in X*/*) cd `expr X$0 : 'X\(.*\)/'` ;; Xesac Xecho "Extracting h2ph (with variable substitutions)" X: This section of the file will have variable substitutions done on it. X: Move anything that needs config subs from !NO!SUBS! section to !GROK!THIS!. X: Protect any dollar signs and backticks that you do not want interpreted X: by putting a backslash in front. You may delete these comments. X$spitshell >h2ph <<!GROK!THIS! X#!$bin/perl X'di'; X'ig00'; X X\$perlincl = '$privlib'; X!GROK!THIS! X X: In the following dollars and backticks do not need the extra backslash. X$spitshell >>h2ph <<'!NO!SUBS!' X Xchdir '/usr/include' || die "Can't cd /usr/include"; X X@isatype = split(' ',<<END); X char uchar u_char X short ushort u_short X int uint u_int X long ulong u_long X FILE XEND X X$isatype{@isatype} = (1) x @isatype; X X@ARGV = ('-') unless @ARGV; X Xforeach $file (@ARGV) { X if ($file eq '-') { X open(IN, "-"); X open(OUT, ">-"); X } X else { X ($outfile = $file) =~ s/\.h$/.ph/ || next; X print "$file -> $outfile\n"; X if ($file =~ m|^(.*)/|) { X $dir = $1; X if (!-d "$perlincl/$dir") { X mkdir("$perlincl/$dir",0777); X } X } X open(IN,"$file") || ((warn "Can't open $file: $!\n"),next); X open(OUT,">$perlincl/$outfile") || die "Can't create $outfile: $!\n"; X } X while (<IN>) { X chop; X while (/\\$/) { X chop; X $_ .= <IN>; X chop; X } X if (s:/\*:\200:g) { X s:\*/:\201:g; X s/\200[^\201]*\201//g; # delete single line comments X if (s/\200.*//) { # begin multi-line comment? X $_ .= '/*'; X $_ .= <IN>; X redo; X } X } X if (s/^#\s*//) { X if (s/^define\s+(\w+)//) { X $name = $1; X $new = ''; X s/\s+$//; X if (s/^\(([\w,\s]*)\)//) { X $args = $1; X if ($args ne '') { X foreach $arg (split(/,\s*/,$args)) { X $curargs{$arg} = 1; X } X $args =~ s/\b(\w)/\$$1/g; X $args = "local($args) = \@_;\n$t "; X } X s/^\s+//; X do expr(); X $new =~ s/(["\\])/\\$1/g; X if ($t ne '') { X $new =~ s/(['\\])/\\$1/g; X print OUT $t, X "eval 'sub $name {\n$t ${args}eval \"$new\";\n$t}';\n"; X } X else { X print OUT "sub $name {\n ${args}eval \"$new\";\n}\n"; X } X %curargs = (); X } X else { X s/^\s+//; X do expr(); X $new = 1 if $new eq ''; X if ($t ne '') { X $new =~ s/(['\\])/\\$1/g; X print OUT $t,"eval 'sub $name {",$new,";}';\n"; X } X else { X print OUT $t,"sub $name {",$new,";}\n"; X } X } X } X elsif (/^include <(.*)>/) { X ($incl = $1) =~ s/\.h$/.ph/; X print OUT $t,"require '$incl';\n"; X } X elsif (/^ifdef\s+(\w+)/) { X print OUT $t,"if (defined &$1) {\n"; X $tab += 4; X $t = "\t" x ($tab / 8) . ' ' x ($tab % 8); X } X elsif (/^ifndef\s+(\w+)/) { X print OUT $t,"if (!defined &$1) {\n"; X $tab += 4; X $t = "\t" x ($tab / 8) . ' ' x ($tab % 8); X } X elsif (s/^if\s+//) { X $new = ''; X do expr(); X print OUT $t,"if ($new) {\n"; X $tab += 4; X $t = "\t" x ($tab / 8) . ' ' x ($tab % 8); X } X elsif (s/^elif\s+//) { X $new = ''; X do expr(); X $tab -= 4; X $t = "\t" x ($tab / 8) . ' ' x ($tab % 8); X print OUT $t,"}\n${t}elsif ($new) {\n"; X $tab += 4; X $t = "\t" x ($tab / 8) . ' ' x ($tab % 8); X } X elsif (/^else/) { X $tab -= 4; X $t = "\t" x ($tab / 8) . ' ' x ($tab % 8); X print OUT $t,"}\n${t}else {\n"; X $tab += 4; X $t = "\t" x ($tab / 8) . ' ' x ($tab % 8); X } X elsif (/^endif/) { X $tab -= 4; X $t = "\t" x ($tab / 8) . ' ' x ($tab % 8); X print OUT $t,"}\n"; X } X } X } X print OUT "1;\n"; X} X Xsub expr { X while ($_ ne '') { X s/^(\s+)// && do {$new .= ' '; next;}; X s/^(0x[0-9a-fA-F]+)// && do {$new .= $1; next;}; X s/^(\d+)// && do {$new .= $1; next;}; X s/^("(\\"|[^"])*")// && do {$new .= $1; next;}; X s/^'((\\"|[^"])*)'// && do { X if ($curargs{$1}) { X $new .= "ord('\$$1')"; X } X else { X $new .= "ord('$1')"; X } X next; X }; X s/^sizeof\s*\(([^)]+)\)/{$1}/ && do { X $new .= '$sizeof'; X next; X }; X s/^([_a-zA-Z]\w*)// && do { X $id = $1; X if ($id eq 'struct') { X s/^\s+(\w+)//; X $id .= ' ' . $1; X $isatype{$id} = 1; X } X elsif ($id eq 'unsigned') { X s/^\s+(\w+)//; X $id .= ' ' . $1; X $isatype{$id} = 1; X } X if ($curargs{$id}) { X $new .= '$' . $id; X } X elsif ($id eq 'defined') { X $new .= 'defined'; X } X elsif (/^\(/) { X s/^\((\w),/("$1",/ if $id =~ /^_IO[WR]*$/i; # cheat X $new .= " &$id"; X } X elsif ($isatype{$id}) { X if ($new =~ /{\s*$/) { X $new .= "'$id'"; X } X elsif ($new =~ /\(\s*$/ && /^[\s*]*\)/) { X $new =~ s/\(\s*$//; X s/^[\s*]*\)//; X } X else { X $new .= $id; X } X } X else { X $new .= ' &' . $id; X } X next; X }; X s/^(.)// && do {$new .= $1; next;}; X } X} X############################################################################## X X # These next few lines are legal in both Perl and nroff. X X.00; # finish .ig X X'di \" finish diversion--previous line must be blank X.nr nl 0-1 \" fake up transition to first page again X.nr % 0 \" start at page 1 X'; __END__ ############# From here on it's a standard manual page ############ X.TH H2PH 1 "August 8, 1990" X.AT 3 X.SH NAME Xh2ph \- convert .h C header files to .ph Perl header files X.SH SYNOPSIS X.B h2ph [headerfiles] X.SH DESCRIPTION X.I h2ph Xconverts any C header files specified to the corresponding Perl header file Xformat. XIt is most easily run while in /usr/include: X.nf X X cd /usr/include; h2ph * sys/* X X.fi XIf run with no arguments, filters standard input to standard output. X.SH ENVIRONMENT XNo environment variables are used. X.SH FILES X/usr/include/*.h X.br X/usr/include/sys/*.h X.br Xetc. X.SH AUTHOR XLarry Wall X.SH "SEE ALSO" Xperl(1) X.SH DIAGNOSTICS XThe usual warnings if it can't read or write the files involved. X.SH BUGS XDoesn't construct the %sizeof array for you. X.PP XIt doesn't handle all C constructs, but it does attempt to isolate Xdefinitions inside evals so that you can get at the definitions Xthat it can translate. X.PP XIt's only intended as a rough tool. XYou may need to dicker with the files produced. X.ex X!NO!SUBS! Xchmod 755 h2ph X$eunicefix h2ph Xrm -f h2ph.man Xln h2ph h2ph.man !STUFFY!FUNK! echo " " echo "End of kit 11 (of 36)" cat /dev/null >kit11isdone run='' config='' for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36; do 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." for combo in *:AA; do if test -f "$combo"; then realfile=`basename $combo :AA` cat $realfile:[A-Z][A-Z] >$realfile rm -rf $realfile:[A-Z][A-Z] fi done rm -rf kit*isdone chmod 755 Configure ;; *) echo "You have run$run." echo "You still need to run$todo." ;; esac : Someone might mail this, so... exit exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.