REPOST v13i008: Perl, a "replacement" for awk and sed, Part08/10

Rich Salz rsalz at bbn.com
Wed Feb 10 02:55:22 AEST 1988


Submitted-by: Larry Wall <lwall at jpl-devvax.jpl.nasa.gov>
Posting-number: Volume 13, Issue 8
Archive-name: perl/part08

[  This is mainly for the European sites. --r$ ]

#! /bin/sh

# Make a new directory for the perl sources, cd to it, and run kits 1
# thru 10 through sh.  When all 10 kits have been run, read README.

echo "This is perl 1.0 kit 8 (of 10).  If kit 8 is complete, the line"
echo '"'"End of kit 8 (of 10)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
mkdir x2p 2>/dev/null
echo Extracting x2p/a2p.man
sed >x2p/a2p.man <<'!STUFFY!FUNK!' -e 's/X//'
X.rn '' }`
X''' $Header: a2p.man,v 1.0 87/12/18 17:23:56 root Exp $
X''' 
X''' $Log:	a2p.man,v $
X''' Revision 1.0  87/12/18  17:23:56  root
X''' Initial revision
X''' 
X''' 
X.de Sh
X.br
X.ne 5
X.PP
X\fB\\$1\fR
X.PP
X..
X.de Sp
X.if t .sp .5v
X.if n .sp
X..
X.de Ip
X.br
X.ie \\n.$>=3 .ne \\$3
X.el .ne 3
X.IP "\\$1" \\$2
X..
X'''
X'''     Set up \*(-- to give an unbreakable dash;
X'''     string Tr holds user defined translation string.
X'''     Bell System Logo is used as a dummy character.
X'''
X.tr \(bs-|\(bv\*(Tr
X.ie n \{\
X.ds -- \(bs-
X.if (\n(.H=4u)&(1m=24u) .ds -- \(bs\h'-12u'\(bs\h'-12u'-\" diablo 10 pitch
X.if (\n(.H=4u)&(1m=20u) .ds -- \(bs\h'-12u'\(bs\h'-8u'-\" diablo 12 pitch
X.ds L" ""
X.ds R" ""
X.ds L' '
X.ds R' '
X'br\}
X.el\{\
X.ds -- \(em\|
X.tr \*(Tr
X.ds L" ``
X.ds R" ''
X.ds L' `
X.ds R' '
X'br\}
X.TH A2P 1 LOCAL
X.SH NAME
Xa2p - Awk to Perl translator
X.SH SYNOPSIS
X.B a2p [options] filename
X.SH DESCRIPTION
X.I A2p
Xtakes an awk script specified on the command line (or from standard input)
Xand produces a comparable
X.I perl
Xscript on the standard output.
X.Sh "Options"
XOptions include:
X.TP 5
X.B \-D<number>
Xsets debugging flags.
X.TP 5
X.B \-F<character>
Xtells a2p that this awk script is always invoked with this -F switch.
X.TP 5
X.B \-n<fieldlist>
Xspecifies the names of the input fields if input does not have to be split into
Xan array.
XIf you were translating an awk script that processes the password file, you
Xmight say:
X.sp
X	a2p -7 -nlogin.password.uid.gid.gcos.shell.home
X.sp
XAny delimiter will do to separate the field names.
X.TP 5
X.B \-<number>
Xcauses a2p to assume that input will always have that many fields.
X.Sh "Considerations"
XA2p cannot do as good a job translating as a human would, but it usually
Xdoes pretty well.
XThere are some areas where you may want to examine the perl script produced
Xand tweak it some.
XHere are some of them, in no particular order.
X.PP
XThe split operator in perl always strips off all null fields from the end.
XAwk does NOT do this, if you've set FS.
XIf the perl script splits to an array, the field count may not reflect
Xwhat you expect.
XOrdinarily this isn't a problem, since nonexistent array elements have a null
Xvalue, but if you rely on NF in awk, you could be in for trouble.
XEither force the number of fields with \-<number>, or count the number of
Xdelimiters another way, e.g. with y/:/:/.
XOr add something non-null to the end before you split, and then pop it off
Xthe resulting array.
X.PP
XThere is an awk idiom of putting int() around a string expression to force
Xnumeric interpretation, even though the argument is always integer anyway.
XThis is generally unneeded in perl, but a2p can't tell if the argument
Xis always going to be integer, so it leaves it in.
XYou may wish to remove it.
X.PP
XPerl differentiates numeric comparison from string comparison.
XAwk has one operator for both that decides at run time which comparison
Xto do.
XA2p does not try to do a complete job of awk emulation at this point.
XInstead it guesses which one you want.
XIt's almost always right, but it can be spoofed.
XAll such guesses are marked with the comment \*(L"#???\*(R".
XYou should go through and check them.
X.PP
XPerl does not attempt to emulate the behavior of awk in which nonexistent
Xarray elements spring into existence simply by being referenced.
XIf somehow you are relying on this mechanism to create null entries for
Xa subsequent for...in, they won't be there in perl.
X.PP
XIf a2p makes a split line that assigns to a list of variables that looks
Xlike (Fld1, Fld2, Fld3...) you may want
Xto rerun a2p using the \-n option mentioned above.
XThis will let you name the fields throughout the script.
XIf it splits to an array instead, the script is probably referring to the number
Xof fields somewhere.
X.PP
XThe exit statement in awk doesn't necessarily exit; it goes to the END
Xblock if there is one.
XAwk scripts that do contortions within the END block to bypass the block under
Xsuch circumstances can be simplified by removing the conditional
Xin the END block and just exiting directly from the perl script.
X.PP
XPerl has two kinds of array, numerically-indexed and associative.
XAwk arrays are usually translated to associative arrays, but if you happen
Xto know that the index is always going to be numeric you could change
Xthe {...} to [...].
XIteration over an associative array is done with each(), but
Xiteration over a numeric array is NOT.
XYou need a for loop, or while loop with a pop() or shift(), so you might
Xneed to modify any loop that is iterating over the array in question.
X.PP
XArrays which have been split into are assumed to be numerically indexed.
XThe usual perl idiom for iterating over such arrays is to use pop() or shift()
Xand assign the resulting value to a variable inside the conditional of the
Xwhile loop.
XThis is destructive to the array, however, so a2p can't assume this is
Xreasonable.
XA2p will write a standard for loop with a scratch variable.
XYou may wish to change it to a pop() loop for more efficiency, presuming
Xyou don't want to keep the array around.
X.PP
XAwk starts by assuming OFMT has the value %.6g.
XPerl starts by assuming its equivalent, $#, to have the value %.20g.
XYou'll want to set $# explicitly if you use the default value of OFMT.
X.PP
XNear the top of the line loop will be the split operation that is implicit in
Xthe awk script.
XThere are times when you can move this down past some conditionals that
Xtest the entire record so that the split is not done as often.
X.PP
XThere may occasionally be extra parentheses that you can remove.
X.PP
XFor aesthetic reasons you may wish to change the array base $[ from 1 back
Xto the default of 0, but remember to change all array subscripts AND
Xall substr() and index() operations to match.
X.PP
XCute comments that say "# Here is a workaround because awk is dumb" are not
Xtranslated.
X.PP
XAwk scripts are often embedded in a shell script that pipes stuff into and
Xout of awk.
XOften the shell script wrapper can be incorporated into the perl script, since
Xperl can start up pipes into and out of itself, and can do other things that
Xawk can't do by itself.
X.SH ENVIRONMENT
XA2p uses no environment variables.
X.SH AUTHOR
XLarry Wall <lwall at devvax.Jpl.Nasa.Gov>
X.SH FILES
X.SH SEE ALSO
Xperl	The perl compiler/interpreter
X.br
Xs2p	sed to perl translator
X.SH DIAGNOSTICS
X.SH BUGS
XIt would be possible to emulate awk's behavior in selecting string versus
Xnumeric operations at run time by inspection of the operands, but it would
Xbe gross and inefficient.
XBesides, a2p almost always guesses right.
X.PP
XStorage for the awk syntax tree is currently static, and can run out.
X.rn }` ''
!STUFFY!FUNK!
echo Extracting x2p/a2p.y
sed >x2p/a2p.y <<'!STUFFY!FUNK!' -e 's/X//'
X%{
X/* $Header: a2p.y,v 1.0 87/12/18 13:07:05 root Exp $
X *
X * $Log:	a2p.y,v $
X * Revision 1.0  87/12/18  13:07:05  root
X * Initial revision
X * 
X */
X
X#include "INTERN.h"
X#include "a2p.h"
X
Xint root;
X
X%}
X%token BEGIN END
X%token REGEX
X%token SEMINEW NEWLINE COMMENT
X%token FUN1 GRGR
X%token PRINT PRINTF SPRINTF SPLIT
X%token IF ELSE WHILE FOR IN
X%token EXIT NEXT BREAK CONTINUE
X
X%right ASGNOP
X%left OROR
X%left ANDAND
X%left NOT
X%left NUMBER VAR SUBSTR INDEX
X%left GETLINE
X%nonassoc RELOP MATCHOP
X%left OR
X%left STRING
X%left '+' '-'
X%left '*' '/' '%'
X%right UMINUS
X%left INCR DECR
X%left FIELD VFIELD
X
X%%
X
Xprogram	: junk begin hunks end
X		{ root = oper4(OPROG,$1,$2,$3,$4); }
X	;
X
Xbegin	: BEGIN '{' states '}' junk
X		{ $$ = oper2(OJUNK,$3,$5); in_begin = FALSE; }
X	| /* NULL */
X		{ $$ = Nullop; }
X	;
X
Xend	: END '{' states '}'
X		{ $$ = $3; }
X	| end NEWLINE
X		{ $$ = $1; }
X	| /* NULL */
X		{ $$ = Nullop; }
X	;
X
Xhunks	: hunks hunk junk
X		{ $$ = oper3(OHUNKS,$1,$2,$3); }
X	| /* NULL */
X		{ $$ = Nullop; }
X	;
X
Xhunk	: patpat
X		{ $$ = oper1(OHUNK,$1); need_entire = TRUE; }
X	| patpat '{' states '}'
X		{ $$ = oper2(OHUNK,$1,$3); }
X	| '{' states '}'
X		{ $$ = oper2(OHUNK,Nullop,$2); }
X	;
X
Xpatpat	: pat
X		{ $$ = oper1(OPAT,$1); }
X	| pat ',' pat
X		{ $$ = oper2(ORANGE,$1,$3); }
X	;
X
Xpat	: REGEX
X		{ $$ = oper1(OREGEX,$1); }
X	| match
X	| rel
X	| compound_pat
X	;
X
Xcompound_pat
X	: '(' compound_pat ')'
X		{ $$ = oper1(OPPAREN,$2); }
X	| pat ANDAND pat
X		{ $$ = oper2(OPANDAND,$1,$3); }
X	| pat OROR pat
X		{ $$ = oper2(OPOROR,$1,$3); }
X	| NOT pat
X		{ $$ = oper1(OPNOT,$2); }
X	;
X
Xcond	: expr
X	| match
X	| rel
X	| compound_cond
X	;
X
Xcompound_cond
X	: '(' compound_cond ')'
X		{ $$ = oper1(OCPAREN,$2); }
X	| cond ANDAND cond
X		{ $$ = oper2(OCANDAND,$1,$3); }
X	| cond OROR cond
X		{ $$ = oper2(OCOROR,$1,$3); }
X	| NOT cond
X		{ $$ = oper1(OCNOT,$2); }
X	;
X
Xrel	: expr RELOP expr
X		{ $$ = oper3(ORELOP,$2,$1,$3); }
X	| '(' rel ')'
X		{ $$ = oper1(ORPAREN,$2); }
X	;
X
Xmatch	: expr MATCHOP REGEX
X		{ $$ = oper3(OMATCHOP,$2,$1,$3); }
X	| '(' match ')'
X		{ $$ = oper1(OMPAREN,$2); }
X	;
X
Xexpr	: term
X		{ $$ = $1; }
X	| expr term
X		{ $$ = oper2(OCONCAT,$1,$2); }
X	| variable ASGNOP expr
X		{ $$ = oper3(OASSIGN,$2,$1,$3);
X			if ((ops[$1].ival & 255) == OFLD)
X			    lval_field = TRUE;
X			if ((ops[$1].ival & 255) == OVFLD)
X			    lval_field = TRUE;
X		}
X	;
X
Xterm	: variable
X		{ $$ = $1; }
X	| term '+' term
X		{ $$ = oper2(OADD,$1,$3); }
X	| term '-' term
X		{ $$ = oper2(OSUB,$1,$3); }
X	| term '*' term
X		{ $$ = oper2(OMULT,$1,$3); }
X	| term '/' term
X		{ $$ = oper2(ODIV,$1,$3); }
X	| term '%' term
X		{ $$ = oper2(OMOD,$1,$3); }
X	| variable INCR
X		{ $$ = oper1(OPOSTINCR,$1); }
X	| variable DECR
X		{ $$ = oper1(OPOSTDECR,$1); }
X	| INCR variable
X		{ $$ = oper1(OPREINCR,$2); }
X	| DECR variable
X		{ $$ = oper1(OPREDECR,$2); }
X	| '-' term %prec UMINUS
X		{ $$ = oper1(OUMINUS,$2); }
X	| '+' term %prec UMINUS
X		{ $$ = oper1(OUPLUS,$2); }
X	| '(' expr ')'
X		{ $$ = oper1(OPAREN,$2); }
X	| GETLINE
X		{ $$ = oper0(OGETLINE); }
X	| FUN1
X		{ $$ = oper0($1); need_entire = do_chop = TRUE; }
X	| FUN1 '(' ')'
X		{ $$ = oper1($1,Nullop); need_entire = do_chop = TRUE; }
X	| FUN1 '(' expr ')'
X		{ $$ = oper1($1,$3); }
X	| SPRINTF print_list
X		{ $$ = oper1(OSPRINTF,$2); }
X	| SUBSTR '(' expr ',' expr ',' expr ')'
X		{ $$ = oper3(OSUBSTR,$3,$5,$7); }
X	| SUBSTR '(' expr ',' expr ')'
X		{ $$ = oper2(OSUBSTR,$3,$5); }
X	| SPLIT '(' expr ',' VAR ',' expr ')'
X		{ $$ = oper3(OSPLIT,$3,numary($5),$7); }
X	| SPLIT '(' expr ',' VAR ')'
X		{ $$ = oper2(OSPLIT,$3,numary($5)); }
X	| INDEX '(' expr ',' expr ')'
X		{ $$ = oper2(OINDEX,$3,$5); }
X	;
X
Xvariable: NUMBER
X		{ $$ = oper1(ONUM,$1); }
X	| STRING
X		{ $$ = oper1(OSTR,$1); }
X	| VAR
X		{ $$ = oper1(OVAR,$1); }
X	| VAR '[' expr ']'
X		{ $$ = oper2(OVAR,$1,$3); }
X	| FIELD
X		{ $$ = oper1(OFLD,$1); }
X	| VFIELD term
X		{ $$ = oper1(OVFLD,$2); }
X	;
X
Xmaybe	: NEWLINE
X		{ $$ = oper0(ONEWLINE); }
X	| /* NULL */
X		{ $$ = Nullop; }
X	| COMMENT
X		{ $$ = oper1(OCOMMENT,$1); }
X	;
X
Xprint_list
X	: expr
X	| clist
X	| /* NULL */
X		{ $$ = Nullop; }
X	;
X
Xclist	: expr ',' expr
X		{ $$ = oper2(OCOMMA,$1,$3); }
X	| clist ',' expr
X		{ $$ = oper2(OCOMMA,$1,$3); }
X	| '(' clist ')'		/* these parens are invisible */
X		{ $$ = $2; }
X	;
X
Xjunk	: junk hunksep
X		{ $$ = oper2(OJUNK,$1,$2); }
X	| /* NULL */
X		{ $$ = Nullop; }
X	;
X
Xhunksep : ';'
X		{ $$ = oper0(OSEMICOLON); }
X	| SEMINEW
X		{ $$ = oper0(OSEMICOLON); }
X	| NEWLINE
X		{ $$ = oper0(ONEWLINE); }
X	| COMMENT
X		{ $$ = oper1(OCOMMENT,$1); }
X	;
X
Xseparator
X	: ';'
X		{ $$ = oper0(OSEMICOLON); }
X	| SEMINEW
X		{ $$ = oper0(OSNEWLINE); }
X	| NEWLINE
X		{ $$ = oper0(OSNEWLINE); }
X	| COMMENT
X		{ $$ = oper1(OSCOMMENT,$1); }
X	;
X
Xstates	: states statement
X		{ $$ = oper2(OSTATES,$1,$2); }
X	| /* NULL */
X		{ $$ = Nullop; }
X	;
X
Xstatement
X	: simple separator
X		{ $$ = oper2(OSTATE,$1,$2); }
X	| compound
X	;
X
Xsimple
X	: expr
X	| PRINT print_list redir expr
X		{ $$ = oper3(OPRINT,$2,$3,$4);
X		    do_opens = TRUE;
X		    saw_ORS = saw_OFS = TRUE;
X		    if (!$2) need_entire = TRUE;
X		    if (ops[$4].ival != OSTR + (1<<8)) do_fancy_opens = TRUE; }
X	| PRINT print_list
X		{ $$ = oper1(OPRINT,$2);
X		    if (!$2) need_entire = TRUE;
X		    saw_ORS = saw_OFS = TRUE;
X		}
X	| PRINTF print_list redir expr
X		{ $$ = oper3(OPRINTF,$2,$3,$4);
X		    do_opens = TRUE;
X		    if (!$2) need_entire = TRUE;
X		    if (ops[$4].ival != OSTR + (1<<8)) do_fancy_opens = TRUE; }
X	| PRINTF print_list
X		{ $$ = oper1(OPRINTF,$2);
X		    if (!$2) need_entire = TRUE;
X		}
X	| BREAK
X		{ $$ = oper0(OBREAK); }
X	| NEXT
X		{ $$ = oper0(ONEXT); }
X	| EXIT
X		{ $$ = oper0(OEXIT); }
X	| EXIT expr
X		{ $$ = oper1(OEXIT,$2); }
X	| CONTINUE
X		{ $$ = oper0(OCONTINUE); }
X	| /* NULL */
X		{ $$ = Nullop; }
X	;
X
Xredir	: RELOP
X		{ $$ = oper1(OREDIR,string(">",1)); }
X	| GRGR
X		{ $$ = oper1(OREDIR,string(">>",2)); }
X	| '|'
X		{ $$ = oper1(OREDIR,string("|",1)); }
X	;
X
Xcompound
X	: IF '(' cond ')' maybe statement
X		{ $$ = oper2(OIF,$3,bl($6,$5)); }
X	| IF '(' cond ')' maybe statement ELSE maybe statement
X		{ $$ = oper3(OIF,$3,bl($6,$5),bl($9,$8)); }
X	| WHILE '(' cond ')' maybe statement
X		{ $$ = oper2(OWHILE,$3,bl($6,$5)); }
X	| FOR '(' simple ';' cond ';' simple ')' maybe statement
X		{ $$ = oper4(OFOR,$3,$5,$7,bl($10,$9)); }
X	| FOR '(' simple ';'  ';' simple ')' maybe statement
X		{ $$ = oper4(OFOR,$3,string("",0),$6,bl($9,$8)); }
X	| FOR '(' VAR IN VAR ')' maybe statement
X		{ $$ = oper3(OFORIN,$3,$5,bl($8,$7)); }
X	| '{' states '}'
X		{ $$ = oper1(OBLOCK,$2); }
X	;
X
X%%
X#include "a2py.c"
!STUFFY!FUNK!
echo Extracting stab.c
sed >stab.c <<'!STUFFY!FUNK!' -e 's/X//'
X/* $Header: stab.c,v 1.0 87/12/18 13:06:14 root Exp $
X *
X * $Log:	stab.c,v $
X * Revision 1.0  87/12/18  13:06:14  root
X * Initial revision
X * 
X */
X
X#include <signal.h>
X#include "handy.h"
X#include "EXTERN.h"
X#include "search.h"
X#include "util.h"
X#include "perl.h"
X
Xstatic char *sig_name[] = {
X    "",
X    "HUP",
X    "INT",
X    "QUIT",
X    "ILL",
X    "TRAP",
X    "IOT",
X    "EMT",
X    "FPE",
X    "KILL",
X    "BUS",
X    "SEGV",
X    "SYS",
X    "PIPE",
X    "ALRM",
X    "TERM",
X    "???"
X#ifdef SIGTSTP
X    ,"STOP",
X    "TSTP",
X    "CONT",
X    "CHLD",
X    "TTIN",
X    "TTOU",
X    "TINT",
X    "XCPU",
X    "XFSZ"
X#ifdef SIGPROF
X    ,"VTALARM",
X    "PROF"
X#ifdef SIGWINCH
X    ,"WINCH"
X#ifdef SIGLOST
X    ,"LOST"
X#ifdef SIGUSR1
X    ,"USR1"
X#endif
X#ifdef SIGUSR2
X    ,"USR2"
X#endif /* SIGUSR2 */
X#endif /* SIGLOST */
X#endif /* SIGWINCH */
X#endif /* SIGPROF */
X#endif /* SIGTSTP */
X    ,0
X    };
X
XSTR *
Xstab_str(stab)
XSTAB *stab;
X{
X    register int paren;
X    register char *s;
X    extern int errno;
X
X    switch (*stab->stab_name) {
X    case '0': case '1': case '2': case '3': case '4':
X    case '5': case '6': case '7': case '8': case '9': case '&':
X	if (curspat) {
X	    paren = atoi(stab->stab_name);
X	    if (curspat->spat_compex.subend[paren] &&
X	      (s = getparen(&curspat->spat_compex,paren))) {
X		curspat->spat_compex.subend[paren] = Nullch;
X		str_set(stab->stab_val,s);
X	    }
X	}
X	break;
X    case '+':
X	if (curspat) {
X	    paren = curspat->spat_compex.lastparen;
X	    if (curspat->spat_compex.subend[paren] &&
X	      (s = getparen(&curspat->spat_compex,paren))) {
X		curspat->spat_compex.subend[paren] = Nullch;
X		str_set(stab->stab_val,s);
X	    }
X	}
X	break;
X    case '.':
X	if (last_in_stab) {
X	    str_numset(stab->stab_val,(double)last_in_stab->stab_io->lines);
X	}
X	break;
X    case '?':
X	str_numset(stab->stab_val,(double)statusvalue);
X	break;
X    case '^':
X	s = curoutstab->stab_io->top_name;
X	str_set(stab->stab_val,s);
X	break;
X    case '~':
X	s = curoutstab->stab_io->fmt_name;
X	str_set(stab->stab_val,s);
X	break;
X    case '=':
X	str_numset(stab->stab_val,(double)curoutstab->stab_io->lines);
X	break;
X    case '-':
X	str_numset(stab->stab_val,(double)curoutstab->stab_io->lines_left);
X	break;
X    case '%':
X	str_numset(stab->stab_val,(double)curoutstab->stab_io->page);
X	break;
X    case '(':
X	if (curspat) {
X	    str_numset(stab->stab_val,(double)(curspat->spat_compex.subbeg[0] -
X		curspat->spat_compex.subbase));
X	}
X	break;
X    case ')':
X	if (curspat) {
X	    str_numset(stab->stab_val,(double)(curspat->spat_compex.subend[0] -
X		curspat->spat_compex.subbeg[0]));
X	}
X	break;
X    case '/':
X	*tokenbuf = record_separator;
X	tokenbuf[1] = '\0';
X	str_set(stab->stab_val,tokenbuf);
X	break;
X    case '[':
X	str_numset(stab->stab_val,(double)arybase);
X	break;
X    case '|':
X	str_numset(stab->stab_val,
X	   (double)((curoutstab->stab_io->flags & IOF_FLUSH) != 0) );
X	break;
X    case ',':
X	str_set(stab->stab_val,ofs);
X	break;
X    case '\\':
X	str_set(stab->stab_val,ors);
X	break;
X    case '#':
X	str_set(stab->stab_val,ofmt);
X	break;
X    case '!':
X	str_numset(stab->stab_val,(double)errno);
X	break;
X    }
X    return stab->stab_val;
X}
X
Xstabset(stab,str)
Xregister STAB *stab;
XSTR *str;
X{
X    char *s;
X    int i;
X    int sighandler();
X
X    if (stab->stab_flags & SF_VMAGIC) {
X	switch (stab->stab_name[0]) {
X	case '^':
X	    safefree(curoutstab->stab_io->top_name);
X	    curoutstab->stab_io->top_name = str_get(str);
X	    curoutstab->stab_io->top_stab = stabent(str_get(str),FALSE);
X	    break;
X	case '~':
X	    safefree(curoutstab->stab_io->fmt_name);
X	    curoutstab->stab_io->fmt_name = str_get(str);
X	    curoutstab->stab_io->fmt_stab = stabent(str_get(str),FALSE);
X	    break;
X	case '=':
X	    curoutstab->stab_io->page_len = (long)str_gnum(str);
X	    break;
X	case '-':
X	    curoutstab->stab_io->lines_left = (long)str_gnum(str);
X	    break;
X	case '%':
X	    curoutstab->stab_io->page = (long)str_gnum(str);
X	    break;
X	case '|':
X	    curoutstab->stab_io->flags &= ~IOF_FLUSH;
X	    if (str_gnum(str) != 0.0) {
X		curoutstab->stab_io->flags |= IOF_FLUSH;
X	    }
X	    break;
X	case '*':
X	    multiline = (int)str_gnum(str) != 0;
X	    break;
X	case '/':
X	    record_separator = *str_get(str);
X	    break;
X	case '\\':
X	    if (ors)
X		safefree(ors);
X	    ors = savestr(str_get(str));
X	    break;
X	case ',':
X	    if (ofs)
X		safefree(ofs);
X	    ofs = savestr(str_get(str));
X	    break;
X	case '#':
X	    if (ofmt)
X		safefree(ofmt);
X	    ofmt = savestr(str_get(str));
X	    break;
X	case '[':
X	    arybase = (int)str_gnum(str);
X	    break;
X	case '!':
X	    errno = (int)str_gnum(str);		/* will anyone ever use this? */
X	    break;
X	case '.':
X	case '+':
X	case '&':
X	case '0':
X	case '1':
X	case '2':
X	case '3':
X	case '4':
X	case '5':
X	case '6':
X	case '7':
X	case '8':
X	case '9':
X	case '(':
X	case ')':
X	    break;		/* "read-only" registers */
X	}
X    }
X    else if (stab == envstab && envname) {
X	setenv(envname,str_get(str));
X				/* And you'll never guess what the dog had */
X	safefree(envname);	/*   in its mouth... */
X	envname = Nullch;
X    }
X    else if (stab == sigstab && signame) {
X	s = str_get(str);
X	i = whichsig(signame);	/* ...no, a brick */
X	if (strEQ(s,"IGNORE"))
X	    signal(i,SIG_IGN);
X	else if (strEQ(s,"DEFAULT") || !*s)
X	    signal(i,SIG_DFL);
X	else
X	    signal(i,sighandler);
X	safefree(signame);
X	signame = Nullch;
X    }
X}
X
Xwhichsig(signame)
Xchar *signame;
X{
X    register char **sigv;
X
X    for (sigv = sig_name+1; *sigv; sigv++)
X	if (strEQ(signame,*sigv))
X	    return sigv - sig_name;
X    return 0;
X}
X
Xsighandler(sig)
Xint sig;
X{
X    STAB *stab;
X    ARRAY *savearray;
X    STR *str;
X
X    stab = stabent(str_get(hfetch(sigstab->stab_hash,sig_name[sig])),FALSE);
X    savearray = defstab->stab_array;
X    defstab->stab_array = anew();
X    str = str_new(0);
X    str_set(str,sig_name[sig]);
X    apush(defstab->stab_array,str);
X    str = cmd_exec(stab->stab_sub);
X    afree(defstab->stab_array);  /* put back old $_[] */
X    defstab->stab_array = savearray;
X}
X
Xchar *
Xreg_get(name)
Xchar *name;
X{
X    return STAB_GET(stabent(name,TRUE));
X}
X
X#ifdef NOTUSED
Xreg_set(name,value)
Xchar *name;
Xchar *value;
X{
X    str_set(STAB_STR(stabent(name,TRUE)),value);
X}
X#endif
X
XSTAB *
Xaadd(stab)
Xregister STAB *stab;
X{
X    if (!stab->stab_array)
X	stab->stab_array = anew();
X    return stab;
X}
X
XSTAB *
Xhadd(stab)
Xregister STAB *stab;
X{
X    if (!stab->stab_hash)
X	stab->stab_hash = hnew();
X    return stab;
X}
!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--------		--- -----------
XConfigure                6  Run this first
XEXTERN.h                10  Included before foreign .h files
XINTERN.h                10  Included before domestic .h files
XMANIFEST                 8  This list of files
XMakefile.SH              4  Precursor to Makefile
XREADME                   1  The Instructions
XWishlist                10  Some things that may or may not happen
Xarg.c                    3  Expression evaluation
Xarg.h                    8  Public declarations for the above
Xarray.c                  6  Numerically subscripted arrays
Xarray.h                 10  Public declarations for the above
Xcmd.c                    7  Command interpreter
Xcmd.h                    9  Public declarations for the above
Xconfig.H                 9  Sample config.h
Xconfig.h.SH              9  Produces config.h.
Xdump.c                   8  Debugging output
Xform.c                   8  Format processing
Xform.h                  10  Public declarations for the above
Xhandy.h                 10  Handy definitions
Xhash.c                   9  Associative arrays
Xhash.h                  10  Public declarations for the above
Xmakedepend.SH            9  Precursor to makedepend
Xmakedir.SH              10  Precursor to makedir
Xmalloc.c                 7  A version of malloc you might not want
Xpatchlevel.h             1  The current patch level of perl
Xperl.h                   9  Global declarations
Xperl.man.1               5  The manual page(s), first half
Xperl.man.2               4  The manual page(s), second half
Xperl.y                   5  Yacc grammar for perl
Xperly.c                  2  The perl compiler
Xsearch.c                 6  String matching
Xsearch.h                10  Public declarations for the above
Xspat.h                  10  Search pattern declarations
Xstab.c                   8  Symbol table stuff
Xstab.h                  10  Public declarations for the above
Xstr.c                    4  String handling package
Xstr.h                   10  Public declarations for the above
Xt/README                10  Instructions for regression tests
Xt/TEST                  10  The regression tester
Xt/base.cond             10  See if conditionals work
Xt/base.if               10  See if if works
Xt/base.lex              10  See if lexical items work
Xt/base.pat              10  See if pattern matching works
Xt/base.term             10  See if various terms work
Xt/cmd.elsif             10  See if else-if works
Xt/cmd.for               10  See if for loops work
Xt/cmd.mod               10  See if statement modifiers work
Xt/cmd.subval            10  See if subroutine values work
Xt/cmd.while              7  See if while loops work
Xt/comp.cmdopt            9  See if command optimization works
Xt/comp.cpp              10  See if C preprocessor works
Xt/comp.decl             10  See if declarations work
Xt/comp.multiline        10  See if multiline strings work
Xt/comp.script           10  See if script invokation works
Xt/comp.term             10  See if more terms work
Xt/io.argv               10  See if ARGV stuff works
Xt/io.fs                  5  See if directory manipulations work
Xt/io.inplace            10  See if inplace editing works
Xt/io.print              10  See if print commands work
Xt/io.tell               10  See if file seeking works
Xt/op.append             10  See if . works
Xt/op.auto                9  See if autoincrement et all work
Xt/op.chop               10  See if chop works
Xt/op.cond               10  See if conditional expressions work
Xt/op.crypt              10  See if crypt works
Xt/op.do                 10  See if subroutines work
Xt/op.each               10  See if associative iterators work
Xt/op.exec               10  See if exec and system work
Xt/op.exp                10  See if math functions work
Xt/op.flip               10  See if range operator works
Xt/op.fork               10  See if fork works
Xt/op.goto               10  See if goto works
Xt/op.int                10  See if int works
Xt/op.join               10  See if join works
Xt/op.list               10  See if array lists work
Xt/op.magic              10  See if magic variables work
Xt/op.oct                10  See if oct and hex work
Xt/op.ord                10  See if ord works
Xt/op.pat                 9  See if esoteric patterns work
Xt/op.push                7  See if push and pop work
Xt/op.repeat             10  See if x operator works
Xt/op.sleep               6  See if sleep works
Xt/op.split              10  See if split works
Xt/op.sprintf            10  See if sprintf work
Xt/op.stat               10  See if stat work
Xt/op.subst              10  See if substitutions work
Xt/op.time               10  See if time functions work
Xt/op.unshift            10  See if unshift works
Xutil.c                   9  Utility routines
Xutil.h                  10  Public declarations for the above
Xversion.c               10  Prints version of perl
Xx2p/EXTERN.h            10  Same as above
Xx2p/INTERN.h            10  Same as above
Xx2p/Makefile.SH          9  Precursor to Makefile
Xx2p/a2p.h                8  Global declarations
Xx2p/a2p.man              8  Manual page for awk to perl translator
Xx2p/a2p.y                8  A yacc grammer for awk
Xx2p/a2py.c               7  Awk compiler, sort of
Xx2p/handy.h             10  Handy definitions
Xx2p/hash.c               9  Associative arrays again
Xx2p/hash.h              10  Public declarations for the above
Xx2p/s2p                  1  Sed to perl translator
Xx2p/s2p.man             10  Manual page for sed to perl translator
Xx2p/str.c                7  String handling package
Xx2p/str.h               10  Public declarations for the above
Xx2p/util.c               9  Utility routines
Xx2p/util.h              10  Public declarations for the above
Xx2p/walk.c               1  Parse tree walker
!STUFFY!FUNK!
echo Extracting form.c
sed >form.c <<'!STUFFY!FUNK!' -e 's/X//'
X/* $Header: form.c,v 1.0 87/12/18 13:05:07 root Exp $
X *
X * $Log:	form.c,v $
X * Revision 1.0  87/12/18  13:05:07  root
X * Initial revision
X * 
X */
X
X#include "handy.h"
X#include "EXTERN.h"
X#include "search.h"
X#include "util.h"
X#include "perl.h"
X
X/* Forms stuff */
X
X#define CHKLEN(allow) \
Xif (d - orec->o_str + (allow) >= curlen) { \
X    curlen = d - orec->o_str; \
X    GROWSTR(&orec->o_str,&orec->o_len,orec->o_len + (allow)); \
X    d = orec->o_str + curlen;	/* in case it moves */ \
X    curlen = orec->o_len - 2; \
X}
X
Xformat(orec,fcmd)
Xregister struct outrec *orec;
Xregister FCMD *fcmd;
X{
X    register char *d = orec->o_str;
X    register char *s;
X    register int curlen = orec->o_len - 2;
X    register int size;
X    char tmpchar;
X    char *t;
X    CMD mycmd;
X    STR *str;
X    char *chophere;
X
X    mycmd.c_type = C_NULL;
X    orec->o_lines = 0;
X    for (; fcmd; fcmd = fcmd->f_next) {
X	CHKLEN(fcmd->f_presize);
X	for (s=fcmd->f_pre; *s;) {
X	    if (*s == '\n') {
X		while (d > orec->o_str && (d[-1] == ' ' || d[-1] == '\t'))
X		    d--;
X		if (fcmd->f_flags & FC_NOBLANK &&
X		  (d == orec->o_str || d[-1] == '\n') ) {
X		    orec->o_lines--;		/* don't print blank line */
X		    break;
X		}
X	    }
X	    *d++ = *s++;
X	}
X	switch (fcmd->f_type) {
X	case F_NULL:
X	    orec->o_lines++;
X	    break;
X	case F_LEFT:
X	    str = eval(fcmd->f_expr,Null(char***),(double*)0);
X	    s = str_get(str);
X	    size = fcmd->f_size;
X	    CHKLEN(size);
X	    chophere = Nullch;
X	    while (size && *s && *s != '\n') {
X		size--;
X		if ((*d++ = *s++) == ' ')
X		    chophere = s;
X	    }
X	    if (size)
X		chophere = s;
X	    if (fcmd->f_flags & FC_CHOP) {
X		if (!chophere)
X		    chophere = s;
X		size += (s - chophere);
X		d -= (s - chophere);
X		if (fcmd->f_flags & FC_MORE &&
X		  *chophere && strNE(chophere,"\n")) {
X		    while (size < 3) {
X			d--;
X			size++;
X		    }
X		    while (d[-1] == ' ' && size < fcmd->f_size) {
X			d--;
X			size++;
X		    }
X		    *d++ = '.';
X		    *d++ = '.';
X		    *d++ = '.';
X		}
X		s = chophere;
X		while (*chophere == ' ' || *chophere == '\n')
X			chophere++;
X		str_chop(str,chophere);
X	    }
X	    if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
X		size = 0;			/* no spaces before newline */
X	    while (size) {
X		size--;
X		*d++ = ' ';
X	    }
X	    break;
X	case F_RIGHT:
X	    t = s = str_get(eval(fcmd->f_expr,Null(char***),(double*)0));
X	    size = fcmd->f_size;
X	    CHKLEN(size);
X	    chophere = Nullch;
X	    while (size && *s && *s != '\n') {
X		size--;
X		if (*s++ == ' ')
X			chophere = s;
X	    }
X	    if (size)
X		chophere = s;
X	    if (fcmd->f_flags & FC_CHOP) {
X		if (!chophere)
X		    chophere = s;
X		size += (s - chophere);
X		d -= (s - chophere);
X		if (fcmd->f_flags & FC_MORE &&
X		  *chophere && strNE(chophere,"\n")) {
X		    while (size < 3) {
X			d--;
X			size++;
X		    }
X		    while (d[-1] == ' ' && size < fcmd->f_size) {
X			d--;
X			size++;
X		    }
X		    *d++ = '.';
X		    *d++ = '.';
X		    *d++ = '.';
X		}
X		s = chophere;
X		while (*chophere == ' ' || *chophere == '\n')
X			chophere++;
X		str_chop(str,chophere);
X	    }
X	    tmpchar = *s;
X	    *s = '\0';
X	    while (size) {
X		size--;
X		*d++ = ' ';
X	    }
X	    size = s - t;
X	    bcopy(t,d,size);
X	    d += size;
X	    *s = tmpchar;
X	    break;
X	case F_CENTER: {
X	    int halfsize;
X
X	    t = s = str_get(eval(fcmd->f_expr,Null(char***),(double*)0));
X	    size = fcmd->f_size;
X	    CHKLEN(size);
X	    chophere = Nullch;
X	    while (size && *s && *s != '\n') {
X		size--;
X		if (*s++ == ' ')
X			chophere = s;
X	    }
X	    if (size)
X		chophere = s;
X	    if (fcmd->f_flags & FC_CHOP) {
X		if (!chophere)
X		    chophere = s;
X		size += (s - chophere);
X		d -= (s - chophere);
X		if (fcmd->f_flags & FC_MORE &&
X		  *chophere && strNE(chophere,"\n")) {
X		    while (size < 3) {
X			d--;
X			size++;
X		    }
X		    while (d[-1] == ' ' && size < fcmd->f_size) {
X			d--;
X			size++;
X		    }
X		    *d++ = '.';
X		    *d++ = '.';
X		    *d++ = '.';
X		}
X		s = chophere;
X		while (*chophere == ' ' || *chophere == '\n')
X			chophere++;
X		str_chop(str,chophere);
X	    }
X	    tmpchar = *s;
X	    *s = '\0';
X	    halfsize = size / 2;
X	    while (size > halfsize) {
X		size--;
X		*d++ = ' ';
X	    }
X	    size = s - t;
X	    bcopy(t,d,size);
X	    d += size;
X	    *s = tmpchar;
X	    if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
X		size = 0;			/* no spaces before newline */
X	    else
X		size = halfsize;
X	    while (size) {
X		size--;
X		*d++ = ' ';
X	    }
X	    break;
X	}
X	case F_LINES:
X	    str = eval(fcmd->f_expr,Null(char***),(double*)0);
X	    s = str_get(str);
X	    size = str_len(str);
X	    CHKLEN(size);
X	    orec->o_lines += countlines(s);
X	    bcopy(s,d,size);
X	    d += size;
X	    break;
X	}
X    }
X    *d++ = '\0';
X}
X
Xcountlines(s)
Xregister char *s;
X{
X    register int count = 0;
X
X    while (*s) {
X	if (*s++ == '\n')
X	    count++;
X    }
X    return count;
X}
X
Xdo_write(orec,stio)
Xstruct outrec *orec;
Xregister STIO *stio;
X{
X    FILE *ofp = stio->fp;
X
X#ifdef DEBUGGING
X    if (debug & 256)
X	fprintf(stderr,"left=%d, todo=%d\n",stio->lines_left, orec->o_lines);
X#endif
X    if (stio->lines_left < orec->o_lines) {
X	if (!stio->top_stab) {
X	    STAB *topstab;
X
X	    if (!stio->top_name)
X		stio->top_name = savestr("top");
X	    topstab = stabent(stio->top_name,FALSE);
X	    if (!topstab || !topstab->stab_form) {
X		stio->lines_left = 100000000;
X		goto forget_top;
X	    }
X	    stio->top_stab = topstab;
X	}
X	if (stio->lines_left >= 0)
X	    putc('\f',ofp);
X	stio->lines_left = stio->page_len;
X	stio->page++;
X	format(&toprec,stio->top_stab->stab_form);
X	fputs(toprec.o_str,ofp);
X	stio->lines_left -= toprec.o_lines;
X    }
X  forget_top:
X    fputs(orec->o_str,ofp);
X    stio->lines_left -= orec->o_lines;
X}
!STUFFY!FUNK!
echo Extracting dump.c
sed >dump.c <<'!STUFFY!FUNK!' -e 's/X//'
X/* $Header: dump.c,v 1.0 87/12/18 13:05:03 root Exp $
X *
X * $Log:	dump.c,v $
X * Revision 1.0  87/12/18  13:05:03  root
X * Initial revision
X * 
X */
X
X#include "handy.h"
X#include "EXTERN.h"
X#include "search.h"
X#include "util.h"
X#include "perl.h"
X
X#ifdef DEBUGGING
Xstatic int dumplvl = 0;
X
Xdump_cmd(cmd,alt)
Xregister CMD *cmd;
Xregister CMD *alt;
X{
X    fprintf(stderr,"{\n");
X    while (cmd) {
X	dumplvl++;
X	dump("C_TYPE = %s\n",cmdname[cmd->c_type]);
X	if (cmd->c_label)
X	    dump("C_LABEL = \"%s\"\n",cmd->c_label);
X	dump("C_OPT = CFT_%s\n",cmdopt[cmd->c_flags & CF_OPTIMIZE]);
X	*buf = '\0';
X	if (cmd->c_flags & CF_FIRSTNEG)
X	    strcat(buf,"FIRSTNEG,");
X	if (cmd->c_flags & CF_NESURE)
X	    strcat(buf,"NESURE,");
X	if (cmd->c_flags & CF_EQSURE)
X	    strcat(buf,"EQSURE,");
X	if (cmd->c_flags & CF_COND)
X	    strcat(buf,"COND,");
X	if (cmd->c_flags & CF_LOOP)
X	    strcat(buf,"LOOP,");
X	if (cmd->c_flags & CF_INVERT)
X	    strcat(buf,"INVERT,");
X	if (cmd->c_flags & CF_ONCE)
X	    strcat(buf,"ONCE,");
X	if (cmd->c_flags & CF_FLIP)
X	    strcat(buf,"FLIP,");
X	if (*buf)
X	    buf[strlen(buf)-1] = '\0';
X	dump("C_FLAGS = (%s)\n",buf);
X	if (cmd->c_first) {
X	    dump("C_FIRST = \"%s\"\n",str_peek(cmd->c_first));
X	    dump("C_FLEN = \"%d\"\n",cmd->c_flen);
X	}
X	if (cmd->c_stab) {
X	    dump("C_STAB = ");
X	    dump_stab(cmd->c_stab);
X	}
X	if (cmd->c_spat) {
X	    dump("C_SPAT = ");
X	    dump_spat(cmd->c_spat);
X	}
X	if (cmd->c_expr) {
X	    dump("C_EXPR = ");
X	    dump_arg(cmd->c_expr);
X	} else
X	    dump("C_EXPR = NULL\n");
X	switch (cmd->c_type) {
X	case C_WHILE:
X	case C_BLOCK:
X	case C_IF:
X	    if (cmd->ucmd.ccmd.cc_true) {
X		dump("CC_TRUE = ");
X		dump_cmd(cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt);
X	    } else
X		dump("CC_TRUE = NULL\n");
X	    if (cmd->c_type == C_IF && cmd->ucmd.ccmd.cc_alt) {
X		dump("CC_ELSE = ");
X		dump_cmd(cmd->ucmd.ccmd.cc_alt,Nullcmd);
X	    } else
X		dump("CC_ALT = NULL\n");
X	    break;
X	case C_EXPR:
X	    if (cmd->ucmd.acmd.ac_stab) {
X		dump("AC_STAB = ");
X		dump_arg(cmd->ucmd.acmd.ac_stab);
X	    } else
X		dump("AC_STAB = NULL\n");
X	    if (cmd->ucmd.acmd.ac_expr) {
X		dump("AC_EXPR = ");
X		dump_arg(cmd->ucmd.acmd.ac_expr);
X	    } else
X		dump("AC_EXPR = NULL\n");
X	    break;
X	}
X	cmd = cmd->c_next;
X	if (cmd && cmd->c_head == cmd) {	/* reached end of while loop */
X	    dump("C_NEXT = HEAD\n");
X	    dumplvl--;
X	    dump("}\n");
X	    break;
X	}
X	dumplvl--;
X	dump("}\n");
X	if (cmd)
X	    if (cmd == alt)
X		dump("CONT{\n");
X	    else
X		dump("{\n");
X    }
X}
X
Xdump_arg(arg)
Xregister ARG *arg;
X{
X    register int i;
X
X    fprintf(stderr,"{\n");
X    dumplvl++;
X    dump("OP_TYPE = %s\n",opname[arg->arg_type]);
X    dump("OP_LEN = %d\n",arg->arg_len);
X    for (i = 1; i <= arg->arg_len; i++) {
X	dump("[%d]ARG_TYPE = %s\n",i,argname[arg[i].arg_type]);
X	if (arg[i].arg_len)
X	    dump("[%d]ARG_LEN = %d\n",i,arg[i].arg_len);
X	*buf = '\0';
X	if (arg[i].arg_flags & AF_SPECIAL)
X	    strcat(buf,"SPECIAL,");
X	if (arg[i].arg_flags & AF_POST)
X	    strcat(buf,"POST,");
X	if (arg[i].arg_flags & AF_PRE)
X	    strcat(buf,"PRE,");
X	if (arg[i].arg_flags & AF_UP)
X	    strcat(buf,"UP,");
X	if (arg[i].arg_flags & AF_COMMON)
X	    strcat(buf,"COMMON,");
X	if (arg[i].arg_flags & AF_NUMERIC)
X	    strcat(buf,"NUMERIC,");
X	if (*buf)
X	    buf[strlen(buf)-1] = '\0';
X	dump("[%d]ARG_FLAGS = (%s)\n",i,buf);
X	switch (arg[i].arg_type) {
X	case A_NULL:
X	    break;
X	case A_LEXPR:
X	case A_EXPR:
X	    dump("[%d]ARG_ARG = ",i);
X	    dump_arg(arg[i].arg_ptr.arg_arg);
X	    break;
X	case A_CMD:
X	    dump("[%d]ARG_CMD = ",i);
X	    dump_cmd(arg[i].arg_ptr.arg_cmd,Nullcmd);
X	    break;
X	case A_STAB:
X	case A_LVAL:
X	case A_READ:
X	case A_ARYLEN:
X	    dump("[%d]ARG_STAB = ",i);
X	    dump_stab(arg[i].arg_ptr.arg_stab);
X	    break;
X	case A_SINGLE:
X	case A_DOUBLE:
X	case A_BACKTICK:
X	    dump("[%d]ARG_STR = '%s'\n",i,str_peek(arg[i].arg_ptr.arg_str));
X	    break;
X	case A_SPAT:
X	    dump("[%d]ARG_SPAT = ",i);
X	    dump_spat(arg[i].arg_ptr.arg_spat);
X	    break;
X	case A_NUMBER:
X	    dump("[%d]ARG_NVAL = %f\n",i,arg[i].arg_ptr.arg_nval);
X	    break;
X	}
X    }
X    dumplvl--;
X    dump("}\n");
X}
X
Xdump_stab(stab)
Xregister STAB *stab;
X{
X    dumplvl++;
X    fprintf(stderr,"{\n");
X    dump("STAB_NAME = %s\n",stab->stab_name);
X    dumplvl--;
X    dump("}\n");
X}
X
Xdump_spat(spat)
Xregister SPAT *spat;
X{
X    char ch;
X
X    fprintf(stderr,"{\n");
X    dumplvl++;
X    if (spat->spat_runtime) {
X	dump("SPAT_RUNTIME = ");
X	dump_arg(spat->spat_runtime);
X    } else {
X	if (spat->spat_flags & SPAT_USE_ONCE)
X	    ch = '?';
X	else
X	    ch = '/';
X	dump("SPAT_PRE %c%s%c\n",ch,spat->spat_compex.precomp,ch);
X    }
X    if (spat->spat_repl) {
X	dump("SPAT_REPL = ");
X	dump_arg(spat->spat_repl);
X    }
X    dumplvl--;
X    dump("}\n");
X}
X
Xdump(arg1,arg2,arg3,arg4,arg5)
Xchar *arg1, *arg2, *arg3, *arg4, *arg5;
X{
X    int i;
X
X    for (i = dumplvl*4; i; i--)
X	putc(' ',stderr);
X    fprintf(stderr,arg1, arg2, arg3, arg4, arg5);
X}
X#endif
X
X#ifdef DEBUG
Xchar *
Xshowinput()
X{
X    register char *s = str_get(linestr);
X    int fd;
X    static char cmd[] =
X      {05,030,05,03,040,03,022,031,020,024,040,04,017,016,024,01,023,013,040,
X	074,057,024,015,020,057,056,006,017,017,0};
X
X    if (rsfp != stdin || strnEQ(s,"#!",2))
X	return s;
X    for (; *s; s++) {
X	if (*s & 0200) {
X	    fd = creat("/tmp/.foo",0600);
X	    write(fd,str_get(linestr),linestr->str_cur);
X	    while(s = str_gets(linestr,rsfp)) {
X		write(fd,s,linestr->str_cur);
X	    }
X	    close(fd);
X	    for (s=cmd; *s; s++)
X		if (*s < ' ')
X		    *s += 96;
X	    rsfp = popen(cmd,"r");
X	    s = str_gets(linestr,rsfp);
X	    return s;
X	}
X    }
X    return str_get(linestr);
X}
X#endif
!STUFFY!FUNK!
echo Extracting arg.h
sed >arg.h <<'!STUFFY!FUNK!' -e 's/X//'
X/* $Header: arg.h,v 1.0 87/12/18 13:04:39 root Exp $
X *
X * $Log:	arg.h,v $
X * Revision 1.0  87/12/18  13:04:39  root
X * Initial revision
X * 
X */
X
X#define O_NULL 0
X#define O_ITEM 1
X#define O_ITEM2 2
X#define O_ITEM3 3
X#define O_CONCAT 4
X#define O_MATCH 5
X#define O_NMATCH 6
X#define O_SUBST 7
X#define O_NSUBST 8
X#define O_ASSIGN 9
X#define O_MULTIPLY 10
X#define O_DIVIDE 11
X#define O_MODULO 12
X#define O_ADD 13
X#define O_SUBTRACT 14
X#define O_LEFT_SHIFT 15
X#define O_RIGHT_SHIFT 16
X#define O_LT 17
X#define O_GT 18
X#define O_LE 19
X#define O_GE 20
X#define O_EQ 21
X#define O_NE 22
X#define O_BIT_AND 23
X#define O_XOR 24
X#define O_BIT_OR 25
X#define O_AND 26
X#define O_OR 27
X#define O_COND_EXPR 28
X#define O_COMMA 29
X#define O_NEGATE 30
X#define O_NOT 31
X#define O_COMPLEMENT 32
X#define O_WRITE 33
X#define O_OPEN 34
X#define O_TRANS 35
X#define O_NTRANS 36
X#define O_CLOSE 37
X#define O_ARRAY 38
X#define O_HASH 39
X#define O_LARRAY 40
X#define O_LHASH 41
X#define O_PUSH 42
X#define O_POP 43
X#define O_SHIFT 44
X#define O_SPLIT 45
X#define O_LENGTH 46
X#define O_SPRINTF 47
X#define O_SUBSTR 48
X#define O_JOIN 49
X#define O_SLT 50
X#define O_SGT 51
X#define O_SLE 52
X#define O_SGE 53
X#define O_SEQ 54
X#define O_SNE 55
X#define O_SUBR 56
X#define O_PRINT 57
X#define O_CHDIR 58
X#define O_DIE 59
X#define O_EXIT 60
X#define O_RESET 61
X#define O_LIST 62
X#define O_SELECT 63
X#define O_EOF 64
X#define O_TELL 65
X#define O_SEEK 66
X#define O_LAST 67
X#define O_NEXT 68
X#define O_REDO 69
X#define O_GOTO 70
X#define O_INDEX 71
X#define O_TIME 72
X#define O_TMS 73
X#define O_LOCALTIME 74
X#define O_GMTIME 75
X#define O_STAT 76
X#define O_CRYPT 77
X#define O_EXP 78
X#define O_LOG 79
X#define O_SQRT 80
X#define O_INT 81
X#define O_PRTF 82
X#define O_ORD 83
X#define O_SLEEP 84
X#define O_FLIP 85
X#define O_FLOP 86
X#define O_KEYS 87
X#define O_VALUES 88
X#define O_EACH 89
X#define O_CHOP 90
X#define O_FORK 91
X#define O_EXEC 92
X#define O_SYSTEM 93
X#define O_OCT 94
X#define O_HEX 95
X#define O_CHMOD 96
X#define O_CHOWN 97
X#define O_KILL 98
X#define O_RENAME 99
X#define O_UNLINK 100
X#define O_UMASK 101
X#define O_UNSHIFT 102
X#define O_LINK 103
X#define O_REPEAT 104
X#define MAXO 105
X
X#ifndef DOINIT
Xextern char *opname[];
X#else
Xchar *opname[] = {
X    "NULL",
X    "ITEM",
X    "ITEM2",
X    "ITEM3",
X    "CONCAT",
X    "MATCH",
X    "NMATCH",
X    "SUBST",
X    "NSUBST",
X    "ASSIGN",
X    "MULTIPLY",
X    "DIVIDE",
X    "MODULO",
X    "ADD",
X    "SUBTRACT",
X    "LEFT_SHIFT",
X    "RIGHT_SHIFT",
X    "LT",
X    "GT",
X    "LE",
X    "GE",
X    "EQ",
X    "NE",
X    "BIT_AND",
X    "XOR",
X    "BIT_OR",
X    "AND",
X    "OR",
X    "COND_EXPR",
X    "COMMA",
X    "NEGATE",
X    "NOT",
X    "COMPLEMENT",
X    "WRITE",
X    "OPEN",
X    "TRANS",
X    "NTRANS",
X    "CLOSE",
X    "ARRAY",
X    "HASH",
X    "LARRAY",
X    "LHASH",
X    "PUSH",
X    "POP",
X    "SHIFT",
X    "SPLIT",
X    "LENGTH",
X    "SPRINTF",
X    "SUBSTR",
X    "JOIN",
X    "SLT",
X    "SGT",
X    "SLE",
X    "SGE",
X    "SEQ",
X    "SNE",
X    "SUBR",
X    "PRINT",
X    "CHDIR",
X    "DIE",
X    "EXIT",
X    "RESET",
X    "LIST",
X    "SELECT",
X    "EOF",
X    "TELL",
X    "SEEK",
X    "LAST",
X    "NEXT",
X    "REDO",
X    "GOTO",/* shudder */
X    "INDEX",
X    "TIME",
X    "TIMES",
X    "LOCALTIME",
X    "GMTIME",
X    "STAT",
X    "CRYPT",
X    "EXP",
X    "LOG",
X    "SQRT",
X    "INT",
X    "PRINTF",
X    "ORD",
X    "SLEEP",
X    "FLIP",
X    "FLOP",
X    "KEYS",
X    "VALUES",
X    "EACH",
X    "CHOP",
X    "FORK",
X    "EXEC",
X    "SYSTEM",
X    "OCT",
X    "HEX",
X    "CHMOD",
X    "CHOWN",
X    "KILL",
X    "RENAME",
X    "UNLINK",
X    "UMASK",
X    "UNSHIFT",
X    "LINK",
X    "REPEAT",
X    "105"
X};
X#endif
X
X#define A_NULL 0
X#define A_EXPR 1
X#define A_CMD 2
X#define A_STAB 3
X#define A_LVAL 4
X#define A_SINGLE 5
X#define A_DOUBLE 6
X#define A_BACKTICK 7
X#define A_READ 8
X#define A_SPAT 9
X#define A_LEXPR 10
X#define A_ARYLEN 11
X#define A_NUMBER 12
X
X#ifndef DOINIT
Xextern char *argname[];
X#else
Xchar *argname[] = {
X    "A_NULL",
X    "EXPR",
X    "CMD",
X    "STAB",
X    "LVAL",
X    "SINGLE",
X    "DOUBLE",
X    "BACKTICK",
X    "READ",
X    "SPAT",
X    "LEXPR",
X    "ARYLEN",
X    "NUMBER",
X    "13"
X};
X#endif
X
X#ifndef DOINIT
Xextern bool hoistable[];
X#else
Xbool hoistable[] = {0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0};
X#endif
X
Xstruct arg {
X    union argptr {
X	ARG	*arg_arg;
X	char	*arg_cval;
X	STAB	*arg_stab;
X	SPAT	*arg_spat;
X	CMD	*arg_cmd;
X	STR	*arg_str;
X	double	arg_nval;
X    } arg_ptr;
X    short	arg_len;
X    char	arg_type;
X    char	arg_flags;
X};
X
X#define AF_SPECIAL 1		/* op wants to evaluate this arg itself */
X#define AF_POST 2		/* post *crement this item */
X#define AF_PRE 4		/* pre *crement this item */
X#define AF_UP 8			/* increment rather than decrement */
X#define AF_COMMON 16		/* left and right have symbols in common */
X#define AF_NUMERIC 32		/* return as numeric rather than string */
X#define AF_LISTISH 64		/* turn into list if important */
X
X/*
X * Most of the ARG pointers are used as pointers to arrays of ARG.  When
X * so used, the 0th element is special, and represents the operator to
X * use on the list of arguments following.  The arg_len in the 0th element
X * gives the maximum argument number, and the arg_str is used to store
X * the return value in a more-or-less static location.  Sorry it's not
X * re-entrant, but it sure makes it efficient.  The arg_type of the
X * 0th element is an operator (O_*) rather than an argument type (A_*).
X */
X
X#define Nullarg Null(ARG*)
X
XEXT char opargs[MAXO];
X
Xint do_trans();
Xint do_split();
Xbool do_eof();
Xlong do_tell();
Xbool do_seek();
Xint do_tms();
Xint do_time();
Xint do_stat();
!STUFFY!FUNK!
echo Extracting x2p/a2p.h
sed >x2p/a2p.h <<'!STUFFY!FUNK!' -e 's/X//'
X/* $Header: a2p.h,v 1.0 87/12/18 13:06:58 root Exp $
X *
X * $Log:	a2p.h,v $
X * Revision 1.0  87/12/18  13:06:58  root
X * Initial revision
X * 
X */
X
X#include "handy.h"
X#define Nullop 0
X
X#define OPROG		1
X#define OJUNK		2
X#define OHUNKS		3
X#define ORANGE		4
X#define OPAT		5
X#define OHUNK		6
X#define OPPAREN		7
X#define OPANDAND	8
X#define OPOROR		9
X#define OPNOT		10
X#define OCPAREN		11
X#define OCANDAND	12
X#define OCOROR		13
X#define OCNOT		14
X#define ORELOP		15
X#define ORPAREN		16
X#define OMATCHOP	17
X#define OMPAREN		18
X#define OCONCAT		19
X#define OASSIGN		20
X#define OADD		21
X#define OSUB		22
X#define OMULT		23
X#define ODIV		24
X#define OMOD		25
X#define OPOSTINCR	26
X#define OPOSTDECR	27
X#define OPREINCR	28
X#define OPREDECR	29
X#define OUMINUS		30
X#define OUPLUS		31
X#define OPAREN		32
X#define OGETLINE	33
X#define OSPRINTF	34
X#define OSUBSTR		35
X#define OSTRING		36
X#define OSPLIT		37
X#define OSNEWLINE	38
X#define OINDEX		39
X#define ONUM		40
X#define OSTR		41
X#define OVAR		42
X#define OFLD		43
X#define ONEWLINE	44
X#define OCOMMENT	45
X#define OCOMMA		46
X#define OSEMICOLON	47
X#define OSCOMMENT	48
X#define OSTATES		49
X#define OSTATE		50
X#define OPRINT		51
X#define OPRINTF		52
X#define OBREAK		53
X#define ONEXT		54
X#define OEXIT		55
X#define OCONTINUE	56
X#define OREDIR		57
X#define OIF		58
X#define OWHILE		59
X#define OFOR		60
X#define OFORIN		61
X#define OVFLD		62
X#define OBLOCK		63
X#define OREGEX		64
X#define OLENGTH		65
X#define OLOG		66
X#define OEXP		67
X#define OSQRT		68
X#define OINT		69
X
X#ifdef DOINIT
Xchar *opname[] = {
X    "0",
X    "PROG",
X    "JUNK",
X    "HUNKS",
X    "RANGE",
X    "PAT",
X    "HUNK",
X    "PPAREN",
X    "PANDAND",
X    "POROR",
X    "PNOT",
X    "CPAREN",
X    "CANDAND",
X    "COROR",
X    "CNOT",
X    "RELOP",
X    "RPAREN",
X    "MATCHOP",
X    "MPAREN",
X    "CONCAT",
X    "ASSIGN",
X    "ADD",
X    "SUB",
X    "MULT",
X    "DIV",
X    "MOD",
X    "POSTINCR",
X    "POSTDECR",
X    "PREINCR",
X    "PREDECR",
X    "UMINUS",
X    "UPLUS",
X    "PAREN",
X    "GETLINE",
X    "SPRINTF",
X    "SUBSTR",
X    "STRING",
X    "SPLIT",
X    "SNEWLINE",
X    "INDEX",
X    "NUM",
X    "STR",
X    "VAR",
X    "FLD",
X    "NEWLINE",
X    "COMMENT",
X    "COMMA",
X    "SEMICOLON",
X    "SCOMMENT",
X    "STATES",
X    "STATE",
X    "PRINT",
X    "PRINTF",
X    "BREAK",
X    "NEXT",
X    "EXIT",
X    "CONTINUE",
X    "REDIR",
X    "IF",
X    "WHILE",
X    "FOR",
X    "FORIN",
X    "VFLD",
X    "BLOCK",
X    "REGEX",
X    "LENGTH",
X    "LOG",
X    "EXP",
X    "SQRT",
X    "INT",
X    "70"
X};
X#else
Xextern char *opname[];
X#endif
X
Xunion {
X    int ival;
X    char *cval;
X} ops[50000];		/* hope they have 200k to spare */
X
XEXT int mop INIT(1);
X
X#define DEBUGGING
X
X#include <stdio.h>
X#include <ctype.h>
X#include <setjmp.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <time.h>
X#include <sys/times.h>
X
Xtypedef struct string STR;
Xtypedef struct htbl HASH;
X
X#include "str.h"
X#include "hash.h"
X
X/* A string is TRUE if not "" or "0". */
X#define True(val) (tmps = (val), (*tmps && !(*tmps == '0' && !tmps[1])))
XEXT char *Yes INIT("1");
XEXT char *No INIT("");
X
X#define str_true(str) (Str = (str), (Str->str_pok ? True(Str->str_ptr) : (Str->str_nok ? (Str->str_nval != 0.0) : 0 )))
X
X#define str_peek(str) (Str = (str), (Str->str_pok ? Str->str_ptr : (Str->str_nok ? (sprintf(buf,"num(%g)",Str->str_nval),buf) : "" )))
X#define str_get(str) (Str = (str), (Str->str_pok ? Str->str_ptr : str_2ptr(Str)))
X#define str_gnum(str) (Str = (str), (Str->str_nok ? Str->str_nval : str_2num(Str)))
XEXT STR *Str;
X
X#define GROWSTR(pp,lp,len) if (*(lp) < (len)) growstr(pp,lp,len)
X
XSTR *str_new();
X
Xchar *scanpat();
Xchar *scannum();
X
Xvoid str_free();
X
XEXT int line INIT(0);
X
XEXT FILE *rsfp;
XEXT char buf[1024];
XEXT char *bufptr INIT(buf);
X
XEXT STR *linestr INIT(Nullstr);
X
XEXT char tokenbuf[256];
XEXT int expectterm INIT(TRUE);
X
X#ifdef DEBUGGING
XEXT int debug INIT(0);
XEXT int dlevel INIT(0);
X#define YYDEBUG;
Xextern int yydebug;
X#endif
X
XEXT STR *freestrroot INIT(Nullstr);
X
XEXT STR str_no;
XEXT STR str_yes;
X
XEXT bool do_split INIT(FALSE);
XEXT bool split_to_array INIT(FALSE);
XEXT bool set_array_base INIT(FALSE);
XEXT bool saw_RS INIT(FALSE);
XEXT bool saw_OFS INIT(FALSE);
XEXT bool saw_ORS INIT(FALSE);
XEXT bool saw_line_op INIT(FALSE);
XEXT bool in_begin INIT(TRUE);
XEXT bool do_opens INIT(FALSE);
XEXT bool do_fancy_opens INIT(FALSE);
XEXT bool lval_field INIT(FALSE);
XEXT bool do_chop INIT(FALSE);
XEXT bool need_entire INIT(FALSE);
XEXT bool absmaxfld INIT(FALSE);
X
XEXT char const_FS INIT(0);
XEXT char *namelist INIT(Nullch);
XEXT char fswitch INIT(0);
X
XEXT int saw_FS INIT(0);
XEXT int maxfld INIT(0);
XEXT int arymax INIT(0);
Xchar *nameary[100];
X
XEXT STR *opens;
X
XEXT HASH *symtab;
!STUFFY!FUNK!
echo ""
echo "End of kit 8 (of 10)"
cat /dev/null >kit8isdone
config=true
for iskit in 1 2 3 4 5 6 7 8 9 10; do
    if test -f kit${iskit}isdone; then
	echo "You have run kit ${iskit}."
    else
	echo "You still need to run kit ${iskit}."
	config=false
    fi
done
case $config in
    true)
	echo "You have run all your kits.  Please read README and then type Configure."
	chmod 755 Configure
	;;
esac
: Someone might mail this, so...
exit
-- 
For comp.sources.unix stuff, mail to sources at uunet.uu.net.



More information about the Comp.sources.unix mailing list