home *** CD-ROM | disk | FTP | other *** search
- Subject: v15i093: Perl, release 2, Part04/15
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Larry Wall <lwall@jpl-devvax.jpl.nasa.gov>
- Posting-number: Volume 15, Issue 93
- Archive-name: perl2/part04
-
- #! /bin/sh
-
- # Make a new directory for the perl sources, cd to it, and run kits 1
- # thru 15 through sh. When all 15 kits have been run, read README.
-
- echo "This is perl 2.0 kit 4 (of 15). If kit 4 is complete, the line"
- echo '"'"End of kit 4 (of 15)"'" will echo at the end.'
- echo ""
- export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
- mkdir x2p 2>/dev/null
- echo Extracting perly.c
- sed >perly.c <<'!STUFFY!FUNK!' -e 's/X//'
- Xchar rcsid[] = "$Header: perly.c,v 2.0 88/06/05 00:09:56 root Exp $";
- X/*
- X * $Log: perly.c,v $
- X * Revision 2.0 88/06/05 00:09:56 root
- X * Baseline version 2.0.
- X *
- X */
- X
- X#include "EXTERN.h"
- X#include "perl.h"
- X#include "perly.h"
- X
- Xextern char *tokename[];
- Xextern int yychar;
- X
- Xstatic int cmd_tosave();
- Xstatic int arg_tosave();
- Xstatic int spat_tosave();
- X
- Xmain(argc,argv,env)
- Xregister int argc;
- Xregister char **argv;
- Xregister char **env;
- X{
- X register STR *str;
- X register char *s;
- X char *index(), *strcpy(), *getenv();
- X bool dosearch = FALSE;
- X
- X uid = (int)getuid();
- X euid = (int)geteuid();
- X linestr = str_new(80);
- X str_nset(linestr,"",0);
- X str = str_make(""); /* first used for -I flags */
- X incstab = aadd(stabent("INC",TRUE));
- X for (argc--,argv++; argc; argc--,argv++) {
- X if (argv[0][0] != '-' || !argv[0][1])
- X break;
- X reswitch:
- X switch (argv[0][1]) {
- X case 'a':
- X minus_a = TRUE;
- X strcpy(argv[0], argv[0]+1);
- X goto reswitch;
- X#ifdef DEBUGGING
- X case 'D':
- X debug = atoi(argv[0]+2);
- X#ifdef YYDEBUG
- X yydebug = (debug & 1);
- X#endif
- X break;
- X#endif
- X case 'e':
- X if (!e_fp) {
- X e_tmpname = strcpy(safemalloc(sizeof(TMPPATH)),TMPPATH);
- X mktemp(e_tmpname);
- X e_fp = fopen(e_tmpname,"w");
- X }
- X if (argv[1])
- X fputs(argv[1],e_fp);
- X putc('\n', e_fp);
- X argc--,argv++;
- X break;
- X case 'i':
- X inplace = savestr(argv[0]+2);
- X argvoutstab = stabent("ARGVOUT",TRUE);
- X break;
- X case 'I':
- X str_cat(str,argv[0]);
- X str_cat(str," ");
- X if (argv[0][2]) {
- X apush(incstab->stab_array,str_make(argv[0]+2));
- X }
- X else {
- X apush(incstab->stab_array,str_make(argv[1]));
- X str_cat(str,argv[1]);
- X argc--,argv++;
- X str_cat(str," ");
- X }
- X break;
- X case 'n':
- X minus_n = TRUE;
- X strcpy(argv[0], argv[0]+1);
- X goto reswitch;
- X case 'p':
- X minus_p = TRUE;
- X strcpy(argv[0], argv[0]+1);
- X goto reswitch;
- X case 'P':
- X preprocess = TRUE;
- X strcpy(argv[0], argv[0]+1);
- X goto reswitch;
- X case 's':
- X doswitches = TRUE;
- X strcpy(argv[0], argv[0]+1);
- X goto reswitch;
- X case 'S':
- X dosearch = TRUE;
- X strcpy(argv[0], argv[0]+1);
- X goto reswitch;
- X case 'U':
- X unsafe = TRUE;
- X strcpy(argv[0], argv[0]+1);
- X goto reswitch;
- X case 'v':
- X version();
- X exit(0);
- X case 'w':
- X dowarn = TRUE;
- X strcpy(argv[0], argv[0]+1);
- X goto reswitch;
- X case '-':
- X argc--,argv++;
- X goto switch_end;
- X case 0:
- X break;
- X default:
- X fatal("Unrecognized switch: %s",argv[0]);
- X }
- X }
- X switch_end:
- X if (e_fp) {
- X fclose(e_fp);
- X argc++,argv--;
- X argv[0] = e_tmpname;
- X }
- X#ifndef PRIVLIB
- X#define PRIVLIB "/usr/local/lib/perl"
- X#endif
- X apush(incstab->stab_array,str_make(PRIVLIB));
- X
- X str_set(&str_no,No);
- X str_set(&str_yes,Yes);
- X init_eval();
- X
- X /* open script */
- X
- X if (argv[0] == Nullch)
- X argv[0] = "-";
- X if (dosearch && argv[0][0] != '/' && (s = getenv("PATH"))) {
- X char *xfound = Nullch, *xfailed = Nullch;
- X
- X while (*s) {
- X s = cpytill(tokenbuf,s,':');
- X if (*s)
- X s++;
- X if (tokenbuf[0])
- X strcat(tokenbuf,"/");
- X strcat(tokenbuf,argv[0]);
- X#ifdef DEBUGGING
- X if (debug & 1)
- X fprintf(stderr,"Looking for %s\n",tokenbuf);
- X#endif
- X if (stat(tokenbuf,&statbuf) < 0) /* not there? */
- X continue;
- X if ((statbuf.st_mode & S_IFMT) == S_IFREG
- X && cando(S_IREAD,TRUE) && cando(S_IEXEC,TRUE)) {
- X xfound = tokenbuf; /* bingo! */
- X break;
- X }
- X if (!xfailed)
- X xfailed = savestr(tokenbuf);
- X }
- X if (!xfound)
- X fatal("Can't execute %s", xfailed);
- X if (xfailed)
- X safefree(xfailed);
- X argv[0] = savestr(xfound);
- X }
- X filename = savestr(argv[0]);
- X origfilename = savestr(filename);
- X if (strEQ(filename,"-"))
- X argv[0] = "";
- X if (preprocess) {
- X str_cat(str,"-I");
- X str_cat(str,PRIVLIB);
- X sprintf(buf, "\
- X/bin/sed -e '/^[^#]/b' \
- X -e '/^#[ ]*include[ ]/b' \
- X -e '/^#[ ]*define[ ]/b' \
- X -e '/^#[ ]*if[ ]/b' \
- X -e '/^#[ ]*ifdef[ ]/b' \
- X -e '/^#[ ]*ifndef[ ]/b' \
- X -e '/^#[ ]*else/b' \
- X -e '/^#[ ]*endif/b' \
- X -e 's/^#.*//' \
- X %s | %s -C %s %s",
- X argv[0], CPPSTDIN, str_get(str), CPPMINUS);
- X rsfp = popen(buf,"r");
- X }
- X else if (!*argv[0])
- X rsfp = stdin;
- X else
- X rsfp = fopen(argv[0],"r");
- X if (rsfp == Nullfp)
- X fatal("Perl script \"%s\" doesn't seem to exist",filename);
- X str_free(str); /* free -I directories */
- X
- X defstab = stabent("_",TRUE);
- X
- X /* init tokener */
- X
- X bufptr = str_get(linestr);
- X
- X /* now parse the report spec */
- X
- X if (yyparse())
- X fatal("Execution aborted due to compilation errors.\n");
- X
- X if (dowarn) {
- X stab_check('A','Z');
- X stab_check('a','z');
- X }
- X
- X preprocess = FALSE;
- X if (e_fp) {
- X e_fp = Nullfp;
- X UNLINK(e_tmpname);
- X }
- X argc--,argv++; /* skip name of script */
- X if (doswitches) {
- X for (; argc > 0 && **argv == '-'; argc--,argv++) {
- X if (argv[0][1] == '-') {
- X argc--,argv++;
- X break;
- X }
- X str_numset(stabent(argv[0]+1,TRUE)->stab_val,(double)1.0);
- X }
- X }
- X if (argvstab = stabent("ARGV",allstabs)) {
- X aadd(argvstab);
- X for (; argc > 0; argc--,argv++) {
- X apush(argvstab->stab_array,str_make(argv[0]));
- X }
- X }
- X if (envstab = stabent("ENV",allstabs)) {
- X hadd(envstab);
- X for (; *env; env++) {
- X if (!(s = index(*env,'=')))
- X continue;
- X *s++ = '\0';
- X str = str_make(s);
- X str->str_link.str_magic = envstab;
- X hstore(envstab->stab_hash,*env,str);
- X *--s = '=';
- X }
- X }
- X if (sigstab = stabent("SIG",allstabs))
- X hadd(sigstab);
- X
- X magicalize("!#?^~=-%0123456789.+&*()<>,\\/[|");
- X
- X sawampersand = (stabent("&",FALSE) != Nullstab);
- X if (tmpstab = stabent("0",allstabs))
- X str_set(STAB_STR(tmpstab),origfilename);
- X if (tmpstab = stabent("$",allstabs))
- X str_numset(STAB_STR(tmpstab),(double)getpid());
- X
- X tmpstab = stabent("stdin",TRUE);
- X tmpstab->stab_io = stio_new();
- X tmpstab->stab_io->fp = stdin;
- X
- X tmpstab = stabent("stdout",TRUE);
- X tmpstab->stab_io = stio_new();
- X tmpstab->stab_io->fp = stdout;
- X defoutstab = tmpstab;
- X curoutstab = tmpstab;
- X
- X tmpstab = stabent("stderr",TRUE);
- X tmpstab->stab_io = stio_new();
- X tmpstab->stab_io->fp = stderr;
- X
- X savestack = anew(Nullstab); /* for saving non-local values */
- X
- X setjmp(top_env); /* sets goto_targ on longjump */
- X
- X#ifdef DEBUGGING
- X if (debug & 1024)
- X dump_cmd(main_root,Nullcmd);
- X if (debug)
- X fprintf(stderr,"\nEXECUTING...\n\n");
- X#endif
- X
- X /* do it */
- X
- X (void) cmd_exec(main_root);
- X
- X if (goto_targ)
- X fatal("Can't find label \"%s\"--aborting",goto_targ);
- X exit(0);
- X /* NOTREACHED */
- X}
- X
- Xmagicalize(list)
- Xregister char *list;
- X{
- X register STAB *stab;
- X char sym[2];
- X
- X sym[1] = '\0';
- X while (*sym = *list++) {
- X if (stab = stabent(sym,allstabs)) {
- X stab->stab_flags = SF_VMAGIC;
- X stab->stab_val->str_link.str_magic = stab;
- X }
- X }
- X}
- X
- XARG *
- Xmake_split(stab,arg)
- Xregister STAB *stab;
- Xregister ARG *arg;
- X{
- X register SPAT *spat = (SPAT *) safemalloc(sizeof (SPAT));
- X
- X if (arg->arg_type != O_MATCH) {
- X spat = (SPAT *) safemalloc(sizeof (SPAT));
- X bzero((char *)spat, sizeof(SPAT));
- X spat->spat_next = spat_root; /* link into spat list */
- X spat_root = spat;
- X
- X spat->spat_runtime = arg;
- X arg = make_match(O_MATCH,stab2arg(A_STAB,defstab),spat);
- X }
- X arg->arg_type = O_SPLIT;
- X spat = arg[2].arg_ptr.arg_spat;
- X spat->spat_repl = stab2arg(A_STAB,aadd(stab));
- X if (spat->spat_short) { /* exact match can bypass regexec() */
- X if (!((spat->spat_flags & SPAT_SCANFIRST) &&
- X (spat->spat_flags & SPAT_ALL) )) {
- X str_free(spat->spat_short);
- X spat->spat_short = Nullstr;
- X }
- X }
- X return arg;
- X}
- X
- XSUBR *
- Xmake_sub(name,cmd)
- Xchar *name;
- XCMD *cmd;
- X{
- X register SUBR *sub = (SUBR *) safemalloc(sizeof (SUBR));
- X STAB *stab = stabent(name,TRUE);
- X
- X if (stab->stab_sub) {
- X if (dowarn) {
- X line_t oldline = line;
- X
- X if (cmd)
- X line = cmd->c_line;
- X warn("Subroutine %s redefined",name);
- X line = oldline;
- X }
- X cmd_free(stab->stab_sub->cmd);
- X afree(stab->stab_sub->tosave);
- X safefree((char*)stab->stab_sub);
- X }
- X bzero((char *)sub, sizeof(SUBR));
- X sub->cmd = cmd;
- X sub->filename = filename;
- X tosave = anew(Nullstab);
- X tosave->ary_fill = 0; /* make 1 based */
- X cmd_tosave(cmd); /* this builds the tosave array */
- X sub->tosave = tosave;
- X stab->stab_sub = sub;
- X}
- X
- XCMD *
- Xblock_head(tail)
- Xregister CMD *tail;
- X{
- X if (tail == Nullcmd) {
- X return tail;
- X }
- X return tail->c_head;
- X}
- X
- XCMD *
- Xappend_line(head,tail)
- Xregister CMD *head;
- Xregister CMD *tail;
- X{
- X if (tail == Nullcmd)
- X return head;
- X if (!tail->c_head) /* make sure tail is well formed */
- X tail->c_head = tail;
- X if (head != Nullcmd) {
- X tail = tail->c_head; /* get to start of tail list */
- X if (!head->c_head)
- X head->c_head = head; /* start a new head list */
- X while (head->c_next) {
- X head->c_next->c_head = head->c_head;
- X head = head->c_next; /* get to end of head list */
- X }
- X head->c_next = tail; /* link to end of old list */
- X tail->c_head = head->c_head; /* propagate head pointer */
- X }
- X while (tail->c_next) {
- X tail->c_next->c_head = tail->c_head;
- X tail = tail->c_next;
- X }
- X return tail;
- X}
- X
- XCMD *
- Xmake_acmd(type,stab,cond,arg)
- Xint type;
- XSTAB *stab;
- XARG *cond;
- XARG *arg;
- X{
- X register CMD *cmd = (CMD *) safemalloc(sizeof (CMD));
- X
- X bzero((char *)cmd, sizeof(CMD));
- X cmd->c_type = type;
- X cmd->ucmd.acmd.ac_stab = stab;
- X cmd->ucmd.acmd.ac_expr = arg;
- X cmd->c_expr = cond;
- X if (cond) {
- X opt_arg(cmd,1,1);
- X cmd->c_flags |= CF_COND;
- X }
- X if (cmdline != NOLINE) {
- X cmd->c_line = cmdline;
- X cmdline = NOLINE;
- X }
- X cmd->c_file = filename;
- X return cmd;
- X}
- X
- XCMD *
- Xmake_ccmd(type,arg,cblock)
- Xint type;
- Xregister ARG *arg;
- Xstruct compcmd cblock;
- X{
- X register CMD *cmd = (CMD *) safemalloc(sizeof (CMD));
- X
- X bzero((char *)cmd, sizeof(CMD));
- X cmd->c_type = type;
- X cmd->c_expr = arg;
- X cmd->ucmd.ccmd.cc_true = cblock.comp_true;
- X cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
- X if (arg) {
- X opt_arg(cmd,1,0);
- X cmd->c_flags |= CF_COND;
- X }
- X if (cmdline != NOLINE) {
- X cmd->c_line = cmdline;
- X cmdline = NOLINE;
- X }
- X return cmd;
- X}
- X
- Xvoid
- Xopt_arg(cmd,fliporflop,acmd)
- Xregister CMD *cmd;
- Xint fliporflop;
- Xint acmd;
- X{
- X register ARG *arg;
- X int opt = CFT_EVAL;
- X int sure = 0;
- X ARG *arg2;
- X char *tmps; /* for True macro */
- X int context = 0; /* 0 = normal, 1 = before &&, 2 = before || */
- X int flp = fliporflop;
- X
- X if (!cmd)
- X return;
- X arg = cmd->c_expr;
- X
- X /* Can we turn && and || into if and unless? */
- X
- X if (acmd && !cmd->ucmd.acmd.ac_expr &&
- X (arg->arg_type == O_AND || arg->arg_type == O_OR) ) {
- X dehoist(arg,1);
- X dehoist(arg,2);
- X cmd->ucmd.acmd.ac_expr = arg[2].arg_ptr.arg_arg;
- X cmd->c_expr = arg[1].arg_ptr.arg_arg;
- X if (arg->arg_type == O_OR)
- X cmd->c_flags ^= CF_INVERT; /* || is like unless */
- X arg->arg_len = 0;
- X arg_free(arg);
- X arg = cmd->c_expr;
- X }
- X
- X /* Turn "if (!expr)" into "unless (expr)" */
- X
- X while (arg->arg_type == O_NOT) {
- X dehoist(arg,1);
- X cmd->c_flags ^= CF_INVERT; /* flip sense of cmd */
- X cmd->c_expr = arg[1].arg_ptr.arg_arg; /* hoist the rest of expr */
- X free_arg(arg);
- X arg = cmd->c_expr; /* here we go again */
- X }
- X
- X if (!arg->arg_len) { /* sanity check */
- X cmd->c_flags |= opt;
- X return;
- X }
- X
- X /* for "cond .. cond" we set up for the initial check */
- X
- X if (arg->arg_type == O_FLIP)
- X context |= 4;
- X
- X /* for "cond && expr" and "cond || expr" we can ignore expr, sort of */
- X
- X if (arg->arg_type == O_AND)
- X context |= 1;
- X else if (arg->arg_type == O_OR)
- X context |= 2;
- X if (context && arg[flp].arg_type == A_EXPR) {
- X arg = arg[flp].arg_ptr.arg_arg;
- X flp = 1;
- X }
- X
- X if (arg[flp].arg_flags & (AF_PRE|AF_POST)) {
- X cmd->c_flags |= opt;
- X return; /* side effect, can't optimize */
- X }
- X
- X if (arg->arg_type == O_ITEM || arg->arg_type == O_FLIP ||
- X arg->arg_type == O_AND || arg->arg_type == O_OR) {
- X if (arg[flp].arg_type == A_SINGLE) {
- X opt = (str_true(arg[flp].arg_ptr.arg_str) ? CFT_TRUE : CFT_FALSE);
- X cmd->c_short = arg[flp].arg_ptr.arg_str;
- X goto literal;
- X }
- X else if (arg[flp].arg_type == A_STAB || arg[flp].arg_type == A_LVAL) {
- X cmd->c_stab = arg[flp].arg_ptr.arg_stab;
- X opt = CFT_REG;
- X literal:
- X if (!context) { /* no && or ||? */
- X free_arg(arg);
- X cmd->c_expr = Nullarg;
- X }
- X if (!(context & 1))
- X cmd->c_flags |= CF_EQSURE;
- X if (!(context & 2))
- X cmd->c_flags |= CF_NESURE;
- X }
- X }
- X else if (arg->arg_type == O_MATCH || arg->arg_type == O_SUBST ||
- X arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST) {
- X if ((arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
- X arg[2].arg_type == A_SPAT &&
- X arg[2].arg_ptr.arg_spat->spat_short ) {
- X cmd->c_stab = arg[1].arg_ptr.arg_stab;
- X cmd->c_short = arg[2].arg_ptr.arg_spat->spat_short;
- X cmd->c_slen = arg[2].arg_ptr.arg_spat->spat_slen;
- X if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ALL &&
- X !(arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ONCE) &&
- X (arg->arg_type == O_MATCH || arg->arg_type == O_NMATCH) )
- X sure |= CF_EQSURE; /* (SUBST must be forced even */
- X /* if we know it will work.) */
- X arg[2].arg_ptr.arg_spat->spat_short = Nullstr;
- X arg[2].arg_ptr.arg_spat->spat_slen = 0; /* only one chk */
- X sure |= CF_NESURE; /* normally only sure if it fails */
- X if (arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST)
- X cmd->c_flags |= CF_FIRSTNEG;
- X if (context & 1) { /* only sure if thing is false */
- X if (cmd->c_flags & CF_FIRSTNEG)
- X sure &= ~CF_NESURE;
- X else
- X sure &= ~CF_EQSURE;
- X }
- X else if (context & 2) { /* only sure if thing is true */
- X if (cmd->c_flags & CF_FIRSTNEG)
- X sure &= ~CF_EQSURE;
- X else
- X sure &= ~CF_NESURE;
- X }
- X if (sure & (CF_EQSURE|CF_NESURE)) { /* if we know anything*/
- X if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_SCANFIRST)
- X opt = CFT_SCAN;
- X else
- X opt = CFT_ANCHOR;
- X if (sure == (CF_EQSURE|CF_NESURE) /* really sure? */
- X && arg->arg_type == O_MATCH
- X && context & 4
- X && fliporflop == 1) {
- X spat_free(arg[2].arg_ptr.arg_spat);
- X arg[2].arg_ptr.arg_spat = Nullspat; /* don't do twice */
- X }
- X cmd->c_flags |= sure;
- X }
- X }
- X }
- X else if (arg->arg_type == O_SEQ || arg->arg_type == O_SNE ||
- X arg->arg_type == O_SLT || arg->arg_type == O_SGT) {
- X if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
- X if (arg[2].arg_type == A_SINGLE) {
- X cmd->c_stab = arg[1].arg_ptr.arg_stab;
- X cmd->c_short = arg[2].arg_ptr.arg_str;
- X cmd->c_slen = 30000;
- X switch (arg->arg_type) {
- X case O_SLT: case O_SGT:
- X sure |= CF_EQSURE;
- X cmd->c_flags |= CF_FIRSTNEG;
- X break;
- X case O_SNE:
- X cmd->c_flags |= CF_FIRSTNEG;
- X /* FALL THROUGH */
- X case O_SEQ:
- X sure |= CF_NESURE|CF_EQSURE;
- X break;
- X }
- X if (context & 1) { /* only sure if thing is false */
- X if (cmd->c_flags & CF_FIRSTNEG)
- X sure &= ~CF_NESURE;
- X else
- X sure &= ~CF_EQSURE;
- X }
- X else if (context & 2) { /* only sure if thing is true */
- X if (cmd->c_flags & CF_FIRSTNEG)
- X sure &= ~CF_EQSURE;
- X else
- X sure &= ~CF_NESURE;
- X }
- X if (sure & (CF_EQSURE|CF_NESURE)) {
- X opt = CFT_STROP;
- X cmd->c_flags |= sure;
- X }
- X }
- X }
- X }
- X else if (arg->arg_type == O_EQ || arg->arg_type == O_NE ||
- X arg->arg_type == O_LE || arg->arg_type == O_GE ||
- X arg->arg_type == O_LT || arg->arg_type == O_GT) {
- X if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
- X if (arg[2].arg_type == A_SINGLE) {
- X cmd->c_stab = arg[1].arg_ptr.arg_stab;
- X cmd->c_short = str_nmake(str_gnum(arg[2].arg_ptr.arg_str));
- X cmd->c_slen = arg->arg_type;
- X sure |= CF_NESURE|CF_EQSURE;
- X if (context & 1) { /* only sure if thing is false */
- X sure &= ~CF_EQSURE;
- X }
- X else if (context & 2) { /* only sure if thing is true */
- X sure &= ~CF_NESURE;
- X }
- X if (sure & (CF_EQSURE|CF_NESURE)) {
- X opt = CFT_NUMOP;
- X cmd->c_flags |= sure;
- X }
- X }
- X }
- X }
- X else if (arg->arg_type == O_ASSIGN &&
- X (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
- X arg[1].arg_ptr.arg_stab == defstab &&
- X arg[2].arg_type == A_EXPR ) {
- X arg2 = arg[2].arg_ptr.arg_arg;
- X if (arg2->arg_type == O_ITEM && arg2[1].arg_type == A_READ) {
- X opt = CFT_GETS;
- X cmd->c_stab = arg2[1].arg_ptr.arg_stab;
- X if (!(arg2[1].arg_ptr.arg_stab->stab_io->flags & IOF_ARGV)) {
- X free_arg(arg2);
- X free_arg(arg);
- X cmd->c_expr = Nullarg;
- X }
- X }
- X }
- X else if (arg->arg_type == O_CHOP &&
- X (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) ) {
- X opt = CFT_CHOP;
- X cmd->c_stab = arg[1].arg_ptr.arg_stab;
- X free_arg(arg);
- X cmd->c_expr = Nullarg;
- X }
- X if (context & 4)
- X opt |= CF_FLIP;
- X cmd->c_flags |= opt;
- X
- X if (cmd->c_flags & CF_FLIP) {
- X if (fliporflop == 1) {
- X arg = cmd->c_expr; /* get back to O_FLIP arg */
- X arg[3].arg_ptr.arg_cmd = (CMD*)safemalloc(sizeof(CMD));
- X bcopy((char *)cmd, (char *)arg[3].arg_ptr.arg_cmd, sizeof(CMD));
- X arg[4].arg_ptr.arg_cmd = (CMD*)safemalloc(sizeof(CMD));
- X bcopy((char *)cmd, (char *)arg[4].arg_ptr.arg_cmd, sizeof(CMD));
- X opt_arg(arg[4].arg_ptr.arg_cmd,2,acmd);
- X arg->arg_len = 2; /* this is a lie */
- X }
- X else {
- X if ((opt & CF_OPTIMIZE) == CFT_EVAL)
- X cmd->c_flags = (cmd->c_flags & ~CF_OPTIMIZE) | CFT_UNFLIP;
- X }
- X }
- X}
- X
- XARG *
- Xmod_match(type,left,pat)
- Xregister ARG *left;
- Xregister ARG *pat;
- X{
- X
- X register SPAT *spat;
- X register ARG *newarg;
- X
- X if ((pat->arg_type == O_MATCH ||
- X pat->arg_type == O_SUBST ||
- X pat->arg_type == O_TRANS ||
- X pat->arg_type == O_SPLIT
- X ) &&
- X pat[1].arg_ptr.arg_stab == defstab ) {
- X switch (pat->arg_type) {
- X case O_MATCH:
- X newarg = make_op(type == O_MATCH ? O_MATCH : O_NMATCH,
- X pat->arg_len,
- X left,Nullarg,Nullarg,0);
- X break;
- X case O_SUBST:
- X newarg = l(make_op(type == O_MATCH ? O_SUBST : O_NSUBST,
- X pat->arg_len,
- X left,Nullarg,Nullarg,0));
- X break;
- X case O_TRANS:
- X newarg = l(make_op(type == O_MATCH ? O_TRANS : O_NTRANS,
- X pat->arg_len,
- X left,Nullarg,Nullarg,0));
- X break;
- X case O_SPLIT:
- X newarg = make_op(type == O_MATCH ? O_SPLIT : O_SPLIT,
- X pat->arg_len,
- X left,Nullarg,Nullarg,0);
- X break;
- X }
- X if (pat->arg_len >= 2) {
- X newarg[2].arg_type = pat[2].arg_type;
- X newarg[2].arg_ptr = pat[2].arg_ptr;
- X newarg[2].arg_flags = pat[2].arg_flags;
- X if (pat->arg_len >= 3) {
- X newarg[3].arg_type = pat[3].arg_type;
- X newarg[3].arg_ptr = pat[3].arg_ptr;
- X newarg[3].arg_flags = pat[3].arg_flags;
- X }
- X }
- X safefree((char*)pat);
- X }
- X else {
- X spat = (SPAT *) safemalloc(sizeof (SPAT));
- X bzero((char *)spat, sizeof(SPAT));
- X spat->spat_next = spat_root; /* link into spat list */
- X spat_root = spat;
- X
- X spat->spat_runtime = pat;
- X newarg = make_op(type,2,left,Nullarg,Nullarg,0);
- X newarg[2].arg_type = A_SPAT;
- X newarg[2].arg_ptr.arg_spat = spat;
- X newarg[2].arg_flags = AF_SPECIAL;
- X }
- X
- X return newarg;
- X}
- X
- XCMD *
- Xadd_label(lbl,cmd)
- Xchar *lbl;
- Xregister CMD *cmd;
- X{
- X if (cmd)
- X cmd->c_label = lbl;
- X return cmd;
- X}
- X
- XCMD *
- Xaddcond(cmd, arg)
- Xregister CMD *cmd;
- Xregister ARG *arg;
- X{
- X cmd->c_expr = arg;
- X opt_arg(cmd,1,0);
- X cmd->c_flags |= CF_COND;
- X return cmd;
- X}
- X
- XCMD *
- Xaddloop(cmd, arg)
- Xregister CMD *cmd;
- Xregister ARG *arg;
- X{
- X cmd->c_expr = arg;
- X opt_arg(cmd,1,0);
- X cmd->c_flags |= CF_COND|CF_LOOP;
- X if (cmd->c_type == C_BLOCK)
- X cmd->c_flags &= ~CF_COND;
- X else {
- X arg = cmd->ucmd.acmd.ac_expr;
- X if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
- X cmd->c_flags &= ~CF_COND; /* "do {} while" happens at least once */
- X if (arg && arg->arg_type == O_SUBR)
- X cmd->c_flags &= ~CF_COND; /* likewise for "do subr() while" */
- X }
- X return cmd;
- X}
- X
- XCMD *
- Xinvert(cmd)
- Xregister CMD *cmd;
- X{
- X cmd->c_flags ^= CF_INVERT;
- X return cmd;
- X}
- X
- Xyyerror(s)
- Xchar *s;
- X{
- X char tmpbuf[128];
- X char *tname = tmpbuf;
- X
- X if (yychar > 256) {
- X tname = tokename[yychar-256];
- X if (strEQ(tname,"word"))
- X strcpy(tname,tokenbuf);
- X else if (strEQ(tname,"register"))
- X sprintf(tname,"$%s",tokenbuf);
- X else if (strEQ(tname,"array_length"))
- X sprintf(tname,"$#%s",tokenbuf);
- X }
- X else if (!yychar)
- X strcpy(tname,"EOF");
- X else if (yychar < 32)
- X sprintf(tname,"^%c",yychar+64);
- X else if (yychar == 127)
- X strcpy(tname,"^?");
- X else
- X sprintf(tname,"%c",yychar);
- X sprintf(tokenbuf, "%s in file %s at line %d, next token \"%s\"\n",
- X s,filename,line,tname);
- X if (in_eval)
- X str_set(stabent("@",TRUE)->stab_val,tokenbuf);
- X else
- X fputs(tokenbuf,stderr);
- X}
- X
- XARG *
- Xmake_op(type,newlen,arg1,arg2,arg3,dolist)
- Xint type;
- Xint newlen;
- XARG *arg1;
- XARG *arg2;
- XARG *arg3;
- Xint dolist;
- X{
- X register ARG *arg;
- X register ARG *chld;
- X register int doarg;
- X
- X arg = op_new(newlen);
- X arg->arg_type = type;
- X doarg = opargs[type];
- X if (chld = arg1) {
- X if (!(doarg & 1))
- X arg[1].arg_flags |= AF_SPECIAL;
- X if (doarg & 16)
- X arg[1].arg_flags |= AF_NUMERIC;
- X if (chld->arg_type == O_ITEM &&
- X (hoistable[chld[1].arg_type] || chld[1].arg_type == A_LVAL) ) {
- X arg[1].arg_type = chld[1].arg_type;
- X arg[1].arg_ptr = chld[1].arg_ptr;
- X arg[1].arg_flags |= chld[1].arg_flags;
- X free_arg(chld);
- X }
- X else {
- X arg[1].arg_type = A_EXPR;
- X arg[1].arg_ptr.arg_arg = chld;
- X if (dolist & 1) {
- X if (chld->arg_type == O_LIST) {
- X if (newlen == 1) { /* we can hoist entire list */
- X chld->arg_type = type;
- X free_arg(arg);
- X arg = chld;
- X }
- X else {
- X arg[1].arg_flags |= AF_SPECIAL;
- X }
- X }
- X else {
- X switch (chld->arg_type) {
- X case O_ARRAY:
- X if (chld->arg_len == 1)
- X arg[1].arg_flags |= AF_SPECIAL;
- X break;
- X case O_ITEM:
- X if (chld[1].arg_type == A_READ ||
- X chld[1].arg_type == A_INDREAD ||
- X chld[1].arg_type == A_GLOB)
- X arg[1].arg_flags |= AF_SPECIAL;
- X break;
- X case O_SPLIT:
- X case O_TMS:
- X case O_EACH:
- X case O_VALUES:
- X case O_KEYS:
- X case O_SORT:
- X arg[1].arg_flags |= AF_SPECIAL;
- X break;
- X }
- X }
- X }
- X }
- X }
- X if (chld = arg2) {
- X if (!(doarg & 2))
- X arg[2].arg_flags |= AF_SPECIAL;
- X if (doarg & 32)
- X arg[2].arg_flags |= AF_NUMERIC;
- X if (chld->arg_type == O_ITEM &&
- X (hoistable[chld[1].arg_type] ||
- X (type == O_ASSIGN &&
- X ((chld[1].arg_type == A_READ && !(arg[1].arg_flags & AF_SPECIAL))
- X ||
- X (chld[1].arg_type == A_INDREAD && !(arg[1].arg_flags & AF_SPECIAL))
- X ||
- X (chld[1].arg_type == A_GLOB && !(arg[1].arg_flags & AF_SPECIAL))
- X ||
- X chld[1].arg_type == A_BACKTICK ) ) ) ) {
- X arg[2].arg_type = chld[1].arg_type;
- X arg[2].arg_ptr = chld[1].arg_ptr;
- X free_arg(chld);
- X }
- X else {
- X arg[2].arg_type = A_EXPR;
- X arg[2].arg_ptr.arg_arg = chld;
- X if ((dolist & 2) &&
- X (chld->arg_type == O_LIST ||
- X (chld->arg_type == O_ARRAY && chld->arg_len == 1) ))
- X arg[2].arg_flags |= AF_SPECIAL;
- X }
- X }
- X if (chld = arg3) {
- X if (!(doarg & 4))
- X arg[3].arg_flags |= AF_SPECIAL;
- X if (doarg & 64)
- X arg[3].arg_flags |= AF_NUMERIC;
- X if (chld->arg_type == O_ITEM && hoistable[chld[1].arg_type]) {
- X arg[3].arg_type = chld[1].arg_type;
- X arg[3].arg_ptr = chld[1].arg_ptr;
- X free_arg(chld);
- X }
- X else {
- X arg[3].arg_type = A_EXPR;
- X arg[3].arg_ptr.arg_arg = chld;
- X if ((dolist & 4) &&
- X (chld->arg_type == O_LIST ||
- X (chld->arg_type == O_ARRAY && chld->arg_len == 1) ))
- X arg[3].arg_flags |= AF_SPECIAL;
- X }
- X }
- X#ifdef DEBUGGING
- X if (debug & 16) {
- X fprintf(stderr,"%lx <= make_op(%s",arg,opname[arg->arg_type]);
- X if (arg1)
- X fprintf(stderr,",%s=%lx",
- X argname[arg[1].arg_type],arg[1].arg_ptr.arg_arg);
- X if (arg2)
- X fprintf(stderr,",%s=%lx",
- X argname[arg[2].arg_type],arg[2].arg_ptr.arg_arg);
- X if (arg3)
- X fprintf(stderr,",%s=%lx",
- X argname[arg[3].arg_type],arg[3].arg_ptr.arg_arg);
- X fprintf(stderr,")\n");
- X }
- X#endif
- X evalstatic(arg); /* see if we can consolidate anything */
- X return arg;
- X}
- X
- X/* turn 123 into 123 == $. */
- X
- XARG *
- Xflipflip(arg)
- Xregister ARG *arg;
- X{
- X if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_SINGLE) {
- X arg = (ARG*)saferealloc((char*)arg,3*sizeof(ARG));
- X arg->arg_type = O_EQ;
- X arg->arg_len = 2;
- X arg[2].arg_type = A_STAB;
- X arg[2].arg_flags = 0;
- X arg[2].arg_ptr.arg_stab = stabent(".",TRUE);
- X }
- X return arg;
- X}
- X
- Xvoid
- Xevalstatic(arg)
- Xregister ARG *arg;
- X{
- X register STR *str;
- X register STR *s1;
- X register STR *s2;
- X double value; /* must not be register */
- X register char *tmps;
- X int i;
- X unsigned long tmplong;
- X double exp(), log(), sqrt(), modf();
- X char *crypt();
- X
- X if (!arg || !arg->arg_len)
- X return;
- X
- X if (arg[1].arg_type == A_SINGLE &&
- X (arg->arg_len == 1 || arg[2].arg_type == A_SINGLE) ) {
- X str = str_new(0);
- X s1 = arg[1].arg_ptr.arg_str;
- X if (arg->arg_len > 1)
- X s2 = arg[2].arg_ptr.arg_str;
- X else
- X s2 = Nullstr;
- X switch (arg->arg_type) {
- X default:
- X str_free(str);
- X str = Nullstr; /* can't be evaluated yet */
- X break;
- X case O_CONCAT:
- X str_sset(str,s1);
- X str_scat(str,s2);
- X break;
- X case O_REPEAT:
- X i = (int)str_gnum(s2);
- X while (i-- > 0)
- X str_scat(str,s1);
- X break;
- X case O_MULTIPLY:
- X value = str_gnum(s1);
- X str_numset(str,value * str_gnum(s2));
- X break;
- X case O_DIVIDE:
- X value = str_gnum(s2);
- X if (value == 0.0)
- X fatal("Illegal division by constant zero");
- X str_numset(str,str_gnum(s1) / value);
- X break;
- X case O_MODULO:
- X tmplong = (unsigned long)str_gnum(s2);
- X if (tmplong == 0L)
- X fatal("Illegal modulus of constant zero");
- X str_numset(str,(double)(((unsigned long)str_gnum(s1)) % tmplong));
- X break;
- X case O_ADD:
- X value = str_gnum(s1);
- X str_numset(str,value + str_gnum(s2));
- X break;
- X case O_SUBTRACT:
- X value = str_gnum(s1);
- X str_numset(str,value - str_gnum(s2));
- X break;
- X case O_LEFT_SHIFT:
- X value = str_gnum(s1);
- X i = (int)str_gnum(s2);
- X str_numset(str,(double)(((unsigned long)value) << i));
- X break;
- X case O_RIGHT_SHIFT:
- X value = str_gnum(s1);
- X i = (int)str_gnum(s2);
- X str_numset(str,(double)(((unsigned long)value) >> i));
- X break;
- X case O_LT:
- X value = str_gnum(s1);
- X str_numset(str,(double)(value < str_gnum(s2)));
- X break;
- X case O_GT:
- X value = str_gnum(s1);
- X str_numset(str,(double)(value > str_gnum(s2)));
- X break;
- X case O_LE:
- X value = str_gnum(s1);
- X str_numset(str,(double)(value <= str_gnum(s2)));
- X break;
- X case O_GE:
- X value = str_gnum(s1);
- X str_numset(str,(double)(value >= str_gnum(s2)));
- X break;
- X case O_EQ:
- X value = str_gnum(s1);
- X str_numset(str,(double)(value == str_gnum(s2)));
- X break;
- X case O_NE:
- X value = str_gnum(s1);
- X str_numset(str,(double)(value != str_gnum(s2)));
- X break;
- X case O_BIT_AND:
- X value = str_gnum(s1);
- X str_numset(str,(double)(((unsigned long)value) &
- X ((unsigned long)str_gnum(s2))));
- X break;
- X case O_XOR:
- X value = str_gnum(s1);
- X str_numset(str,(double)(((unsigned long)value) ^
- X ((unsigned long)str_gnum(s2))));
- X break;
- X case O_BIT_OR:
- X value = str_gnum(s1);
- X str_numset(str,(double)(((unsigned long)value) |
- X ((unsigned long)str_gnum(s2))));
- X break;
- X case O_AND:
- X if (str_true(s1))
- X str = str_make(str_get(s2));
- X else
- X str = str_make(str_get(s1));
- X break;
- X case O_OR:
- X if (str_true(s1))
- X str = str_make(str_get(s1));
- X else
- X str = str_make(str_get(s2));
- X break;
- X case O_COND_EXPR:
- X if (arg[3].arg_type != A_SINGLE) {
- X str_free(str);
- X str = Nullstr;
- X }
- X else {
- X str = str_make(str_get(str_true(s1) ? s2 : arg[3].arg_ptr.arg_str));
- X str_free(arg[3].arg_ptr.arg_str);
- X }
- X break;
- X case O_NEGATE:
- X str_numset(str,(double)(-str_gnum(s1)));
- X break;
- X case O_NOT:
- X str_numset(str,(double)(!str_true(s1)));
- X break;
- X case O_COMPLEMENT:
- X str_numset(str,(double)(~(long)str_gnum(s1)));
- X break;
- X case O_LENGTH:
- X str_numset(str, (double)str_len(s1));
- X break;
- X case O_SUBSTR:
- X if (arg[3].arg_type != A_SINGLE || stabent("[",allstabs)) {
- X str_free(str); /* making the fallacious assumption */
- X str = Nullstr; /* that any $[ occurs before substr()*/
- X }
- X else {
- X char *beg;
- X int len = (int)str_gnum(s2);
- X int tmp;
- X
- X for (beg = str_get(s1); *beg && len > 0; beg++,len--) ;
- X len = (int)str_gnum(arg[3].arg_ptr.arg_str);
- X str_free(arg[3].arg_ptr.arg_str);
- X if (len > (tmp = strlen(beg)))
- X len = tmp;
- X str_nset(str,beg,len);
- X }
- X break;
- X case O_SLT:
- X tmps = str_get(s1);
- X str_numset(str,(double)(strLT(tmps,str_get(s2))));
- X break;
- X case O_SGT:
- X tmps = str_get(s1);
- X str_numset(str,(double)(strGT(tmps,str_get(s2))));
- X break;
- X case O_SLE:
- X tmps = str_get(s1);
- X str_numset(str,(double)(strLE(tmps,str_get(s2))));
- X break;
- X case O_SGE:
- X tmps = str_get(s1);
- X str_numset(str,(double)(strGE(tmps,str_get(s2))));
- X break;
- X case O_SEQ:
- X tmps = str_get(s1);
- X str_numset(str,(double)(strEQ(tmps,str_get(s2))));
- X break;
- X case O_SNE:
- X tmps = str_get(s1);
- X str_numset(str,(double)(strNE(tmps,str_get(s2))));
- X break;
- X case O_CRYPT:
- X#ifdef CRYPT
- X tmps = str_get(s1);
- X str_set(str,crypt(tmps,str_get(s2)));
- X#else
- X fatal(
- X "The crypt() function is unimplemented due to excessive paranoia.");
- X#endif
- X break;
- X case O_EXP:
- X str_numset(str,exp(str_gnum(s1)));
- X break;
- X case O_LOG:
- X str_numset(str,log(str_gnum(s1)));
- X break;
- X case O_SQRT:
- X str_numset(str,sqrt(str_gnum(s1)));
- X break;
- X case O_INT:
- X value = str_gnum(s1);
- X if (value >= 0.0)
- X modf(value,&value);
- X else {
- X modf(-value,&value);
- X value = -value;
- X }
- X str_numset(str,value);
- X break;
- X case O_ORD:
- X str_numset(str,(double)(*str_get(s1)));
- X break;
- X }
- X if (str) {
- X arg->arg_type = O_ITEM; /* note arg1 type is already SINGLE */
- X str_free(s1);
- X str_free(s2);
- X arg[1].arg_ptr.arg_str = str;
- X }
- X }
- X}
- X
- XARG *
- Xl(arg)
- Xregister ARG *arg;
- X{
- X register int i;
- X register ARG *arg1;
- X ARG *tmparg;
- X
- X arg->arg_flags |= AF_COMMON; /* XXX should cross-match */
- X /* this does unnecessary copying */
- X
- X if (arg[1].arg_type == A_ARYLEN) {
- X arg[1].arg_type = A_LARYLEN;
- X return arg;
- X }
- X
- X /* see if it's an array reference */
- X
- X if (arg[1].arg_type == A_EXPR) {
- X arg1 = arg[1].arg_ptr.arg_arg;
- X
- X if (arg1->arg_type == O_LIST && arg->arg_type != O_ITEM) {
- X /* assign to list */
- X arg[1].arg_flags |= AF_SPECIAL;
- X dehoist(arg,2);
- X arg[2].arg_flags |= AF_SPECIAL;
- X for (i = arg1->arg_len; i >= 1; i--) {
- X switch (arg1[i].arg_type) {
- X case A_STAB: case A_LVAL:
- X arg1[i].arg_type = A_LVAL;
- X break;
- X case A_EXPR: case A_LEXPR:
- X arg1[i].arg_type = A_LEXPR;
- X if (arg1[i].arg_ptr.arg_arg->arg_type == O_ARRAY)
- X arg1[i].arg_ptr.arg_arg->arg_type = O_LARRAY;
- X else if (arg1[i].arg_ptr.arg_arg->arg_type == O_HASH)
- X arg1[i].arg_ptr.arg_arg->arg_type = O_LHASH;
- X if (arg1[i].arg_ptr.arg_arg->arg_type == O_LARRAY)
- X break;
- X if (arg1[i].arg_ptr.arg_arg->arg_type == O_LHASH)
- X break;
- X /* FALL THROUGH */
- X default:
- X sprintf(tokenbuf,
- X "Illegal item (%s) as lvalue",argname[arg1[i].arg_type]);
- X yyerror(tokenbuf);
- X }
- X }
- X }
- X else if (arg1->arg_type == O_ARRAY) {
- X if (arg1->arg_len == 1 && arg->arg_type != O_ITEM) {
- X /* assign to array */
- X arg[1].arg_flags |= AF_SPECIAL;
- X dehoist(arg,2);
- X arg[2].arg_flags |= AF_SPECIAL;
- X }
- X else
- X arg1->arg_type = O_LARRAY; /* assign to array elem */
- X }
- X else if (arg1->arg_type == O_HASH)
- X arg1->arg_type = O_LHASH;
- X else if (arg1->arg_type != O_ASSIGN) {
- X sprintf(tokenbuf,
- X "Illegal expression (%s) as lvalue",opname[arg1->arg_type]);
- X yyerror(tokenbuf);
- X }
- X arg[1].arg_type = A_LEXPR;
- X#ifdef DEBUGGING
- X if (debug & 16)
- X fprintf(stderr,"lval LEXPR\n");
- X#endif
- X return arg;
- X }
- X
- X /* not an array reference, should be a register name */
- X
- X if (arg[1].arg_type != A_STAB && arg[1].arg_type != A_LVAL) {
- X sprintf(tokenbuf,
- X "Illegal item (%s) as lvalue",argname[arg[1].arg_type]);
- X yyerror(tokenbuf);
- X }
- X arg[1].arg_type = A_LVAL;
- X#ifdef DEBUGGING
- X if (debug & 16)
- X fprintf(stderr,"lval LVAL\n");
- X#endif
- X return arg;
- X}
- X
- Xdehoist(arg,i)
- XARG *arg;
- X{
- X ARG *tmparg;
- X
- X if (arg[i].arg_type != A_EXPR) { /* dehoist */
- X tmparg = make_op(O_ITEM,1,Nullarg,Nullarg,Nullarg,0);
- X tmparg[1] = arg[i];
- X arg[i].arg_ptr.arg_arg = tmparg;
- X arg[i].arg_type = A_EXPR;
- X }
- X}
- X
- XARG *
- Xaddflags(i,flags,arg)
- Xregister ARG *arg;
- X{
- X arg[i].arg_flags |= flags;
- X return arg;
- X}
- X
- XARG *
- Xhide_ary(arg)
- XARG *arg;
- X{
- X if (arg->arg_type == O_ARRAY)
- X return make_op(O_ITEM,1,arg,Nullarg,Nullarg,0);
- X return arg;
- X}
- X
- XARG *
- Xmake_list(arg)
- Xregister ARG *arg;
- X{
- X register int i;
- X register ARG *node;
- X register ARG *nxtnode;
- X register int j;
- X STR *tmpstr;
- X
- X if (!arg) {
- X arg = op_new(0);
- X arg->arg_type = O_LIST;
- X }
- X if (arg->arg_type != O_COMMA) {
- X arg->arg_flags |= AF_LISTISH; /* see listish() below */
- X return arg;
- X }
- X for (i = 2, node = arg; ; i++) {
- X if (node->arg_len < 2)
- X break;
- X if (node[2].arg_type != A_EXPR)
- X break;
- X node = node[2].arg_ptr.arg_arg;
- X if (node->arg_type != O_COMMA)
- X break;
- X }
- X if (i > 2) {
- X node = arg;
- X arg = op_new(i);
- X tmpstr = arg->arg_ptr.arg_str;
- X *arg = *node; /* copy everything except the STR */
- X arg->arg_ptr.arg_str = tmpstr;
- X for (j = 1; ; ) {
- X arg[j] = node[1];
- X ++j; /* Bug in Xenix compiler */
- X if (j >= i) {
- X arg[j] = node[2];
- X free_arg(node);
- X break;
- X }
- X nxtnode = node[2].arg_ptr.arg_arg;
- X free_arg(node);
- X node = nxtnode;
- X }
- X }
- X arg->arg_type = O_LIST;
- X arg->arg_len = i;
- X return arg;
- X}
- X
- X/* turn a single item into a list */
- X
- XARG *
- Xlistish(arg)
- XARG *arg;
- X{
- X if (arg->arg_flags & AF_LISTISH) {
- X arg = make_op(O_LIST,1,arg,Nullarg,Nullarg,0);
- X arg[1].arg_flags &= ~AF_SPECIAL;
- X }
- X return arg;
- X}
- X
- X/* mark list of local variables */
- X
- XARG *
- Xlocalize(arg)
- XARG *arg;
- X{
- X arg->arg_flags |= AF_LOCAL;
- X return arg;
- X}
- X
- XARG *
- Xstab2arg(atype,stab)
- Xint atype;
- Xregister STAB *stab;
- X{
- X register ARG *arg;
- X
- X arg = op_new(1);
- X arg->arg_type = O_ITEM;
- X arg[1].arg_type = atype;
- X arg[1].arg_ptr.arg_stab = stab;
- X return arg;
- X}
- X
- XARG *
- Xcval_to_arg(cval)
- Xregister char *cval;
- X{
- X register ARG *arg;
- X
- X arg = op_new(1);
- X arg->arg_type = O_ITEM;
- X arg[1].arg_type = A_SINGLE;
- X arg[1].arg_ptr.arg_str = str_make(cval);
- X safefree(cval);
- X return arg;
- X}
- X
- XARG *
- Xop_new(numargs)
- Xint numargs;
- X{
- X register ARG *arg;
- X
- X arg = (ARG*)safemalloc((numargs + 1) * sizeof (ARG));
- X bzero((char *)arg, (numargs + 1) * sizeof (ARG));
- X arg->arg_ptr.arg_str = str_new(0);
- X arg->arg_len = numargs;
- X return arg;
- X}
- X
- Xvoid
- Xfree_arg(arg)
- XARG *arg;
- X{
- X str_free(arg->arg_ptr.arg_str);
- X safefree((char*)arg);
- X}
- X
- XARG *
- Xmake_match(type,expr,spat)
- Xint type;
- XARG *expr;
- XSPAT *spat;
- X{
- X register ARG *arg;
- X
- X arg = make_op(type,2,expr,Nullarg,Nullarg,0);
- X
- X arg[2].arg_type = A_SPAT;
- X arg[2].arg_ptr.arg_spat = spat;
- X#ifdef DEBUGGING
- X if (debug & 16)
- X fprintf(stderr,"make_match SPAT=%lx\n",(long)spat);
- X#endif
- X
- X if (type == O_SUBST || type == O_NSUBST) {
- X if (arg[1].arg_type != A_STAB)
- X yyerror("Illegal lvalue");
- X arg[1].arg_type = A_LVAL;
- X }
- X return arg;
- X}
- X
- XARG *
- Xcmd_to_arg(cmd)
- XCMD *cmd;
- X{
- X register ARG *arg;
- X
- X arg = op_new(1);
- X arg->arg_type = O_ITEM;
- X arg[1].arg_type = A_CMD;
- X arg[1].arg_ptr.arg_cmd = cmd;
- X return arg;
- X}
- X
- XCMD *
- Xwopt(cmd)
- Xregister CMD *cmd;
- X{
- X register CMD *tail;
- X register ARG *arg = cmd->c_expr;
- X STAB *asgnstab;
- X
- X /* hoist "while (<channel>)" up into command block */
- X
- X if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_READ) {
- X cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */
- X cmd->c_flags |= CFT_GETS; /* and set it to do the input */
- X cmd->c_stab = arg[1].arg_ptr.arg_stab;
- X if (arg[1].arg_ptr.arg_stab->stab_io->flags & IOF_ARGV) {
- X cmd->c_expr = l(make_op(O_ASSIGN, 2, /* fake up "$_ =" */
- X stab2arg(A_LVAL,defstab), arg, Nullarg,1 ));
- X }
- X else {
- X free_arg(arg);
- X cmd->c_expr = Nullarg;
- X }
- X }
- X else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_INDREAD) {
- X cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */
- X cmd->c_flags |= CFT_INDGETS; /* and set it to do the input */
- X cmd->c_stab = arg[1].arg_ptr.arg_stab;
- X free_arg(arg);
- X cmd->c_expr = Nullarg;
- X }
- X else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_GLOB) {
- X if ((cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY)
- X asgnstab = cmd->c_stab;
- X else
- X asgnstab = defstab;
- X cmd->c_expr = l(make_op(O_ASSIGN, 2, /* fake up "$foo =" */
- X stab2arg(A_LVAL,asgnstab), arg, Nullarg,1 ));
- X cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */
- X }
- X
- X /* First find the end of the true list */
- X
- X if (cmd->ucmd.ccmd.cc_true == Nullcmd)
- X return cmd;
- X for (tail = cmd->ucmd.ccmd.cc_true; tail->c_next; tail = tail->c_next) ;
- X
- X /* if there's a continue block, link it to true block and find end */
- X
- X if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
- X tail->c_next = cmd->ucmd.ccmd.cc_alt;
- X for ( ; tail->c_next; tail = tail->c_next) ;
- X }
- X
- X /* Here's the real trick: link the end of the list back to the beginning,
- X * inserting a "last" block to break out of the loop. This saves one or
- X * two procedure calls every time through the loop, because of how cmd_exec
- X * does tail recursion.
- X */
- X
- X tail->c_next = (CMD *) safemalloc(sizeof (CMD));
- X tail = tail->c_next;
- X if (!cmd->ucmd.ccmd.cc_alt)
- X cmd->ucmd.ccmd.cc_alt = tail; /* every loop has a continue now */
- X
- X bcopy((char *)cmd, (char *)tail, sizeof(CMD));
- X tail->c_type = C_EXPR;
- X tail->c_flags ^= CF_INVERT; /* turn into "last unless" */
- X tail->c_next = tail->ucmd.ccmd.cc_true; /* loop directly back to top */
- X tail->ucmd.acmd.ac_expr = make_op(O_LAST,0,Nullarg,Nullarg,Nullarg,0);
- X tail->ucmd.acmd.ac_stab = Nullstab;
- X return cmd;
- X}
- X
- XCMD *
- Xover(eachstab,cmd)
- XSTAB *eachstab;
- Xregister CMD *cmd;
- X{
- X /* hoist "for $foo (@bar)" up into command block */
- X
- X cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */
- X cmd->c_flags |= CFT_ARRAY; /* and set it to do the iteration */
- X cmd->c_stab = eachstab;
- X
- X return cmd;
- X}
- X
- Xstatic int gensym = 0;
- X
- XSTAB *
- Xgenstab()
- X{
- X sprintf(tokenbuf,"_GEN_%d",gensym++);
- X return stabent(tokenbuf,TRUE);
- X}
- X
- X/* this routine is in perly.c by virtue of being sort of an alternate main() */
- X
- XSTR *
- Xdo_eval(str,optype)
- XSTR *str;
- Xint optype;
- X{
- X int retval;
- X CMD *myroot;
- X ARRAY *ar;
- X int i;
- X char *oldfile = filename;
- X line_t oldline = line;
- X int oldtmps_base = tmps_base;
- X int oldsave = savestack->ary_fill;
- X
- X tmps_base = tmps_max;
- X str_set(stabent("@",TRUE)->stab_val,"");
- X if (optype != O_DOFILE) { /* normal eval */
- X filename = "(eval)";
- X line = 1;
- X str_sset(linestr,str);
- X }
- X else {
- X filename = savestr(str_get(str)); /* can't free this easily */
- X str_set(linestr,"");
- X rsfp = fopen(filename,"r");
- X ar = incstab->stab_array;
- X if (!rsfp && *filename != '/') {
- X for (i = 0; i <= ar->ary_fill; i++) {
- X sprintf(tokenbuf,"%s/%s",str_get(afetch(ar,i)),filename);
- X rsfp = fopen(tokenbuf,"r");
- X if (rsfp) {
- X free(filename);
- X filename = savestr(tokenbuf);
- X break;
- X }
- X }
- X }
- X if (!rsfp) {
- X filename = oldfile;
- X tmps_base = oldtmps_base;
- X return &str_no;
- X }
- X line = 0;
- X }
- X in_eval++;
- X bufptr = str_get(linestr);
- X if (setjmp(eval_env))
- X retval = 1;
- X else
- X retval = yyparse();
- X myroot = eval_root; /* in case cmd_exec does another eval! */
- X if (retval)
- X str = &str_no;
- X else {
- X str = str_static(cmd_exec(eval_root));
- X /* if we don't save str, free zaps it */
- X cmd_free(myroot); /* can't free on error, for some reason */
- X }
- X in_eval--;
- X filename = oldfile;
- X line = oldline;
- X tmps_base = oldtmps_base;
- X if (savestack->ary_fill > oldsave) /* let them use local() */
- X restorelist(oldsave);
- X return str;
- X}
- X
- Xcmd_free(cmd)
- Xregister CMD *cmd;
- X{
- X register CMD *tofree;
- X register CMD *head = cmd;
- X
- X while (cmd) {
- X if (cmd->c_type != C_WHILE) { /* WHILE block is duplicated */
- X if (cmd->c_label)
- X safefree(cmd->c_label);
- X if (cmd->c_short)
- X str_free(cmd->c_short);
- X if (cmd->c_spat)
- X spat_free(cmd->c_spat);
- X if (cmd->c_expr)
- X arg_free(cmd->c_expr);
- X }
- 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 cmd_free(cmd->ucmd.ccmd.cc_true);
- X if (cmd->c_type == C_IF && cmd->ucmd.ccmd.cc_alt)
- X cmd_free(cmd->ucmd.ccmd.cc_alt);
- X break;
- X case C_EXPR:
- X if (cmd->ucmd.acmd.ac_expr)
- X arg_free(cmd->ucmd.acmd.ac_expr);
- X break;
- X }
- X tofree = cmd;
- X cmd = cmd->c_next;
- X safefree((char*)tofree);
- X if (cmd && cmd == head) /* reached end of while loop */
- X break;
- X }
- X}
- X
- Xarg_free(arg)
- Xregister ARG *arg;
- X{
- X register int i;
- X
- X for (i = 1; i <= arg->arg_len; i++) {
- X switch (arg[i].arg_type) {
- X case A_NULL:
- X break;
- X case A_LEXPR:
- X case A_EXPR:
- X arg_free(arg[i].arg_ptr.arg_arg);
- X break;
- X case A_CMD:
- X cmd_free(arg[i].arg_ptr.arg_cmd);
- X break;
- X case A_WORD:
- X case A_STAB:
- X case A_LVAL:
- X case A_READ:
- X case A_GLOB:
- X case A_ARYLEN:
- X break;
- X case A_SINGLE:
- X case A_DOUBLE:
- X case A_BACKTICK:
- X str_free(arg[i].arg_ptr.arg_str);
- X break;
- X case A_SPAT:
- X spat_free(arg[i].arg_ptr.arg_spat);
- X break;
- X case A_NUMBER:
- X break;
- X }
- X }
- X free_arg(arg);
- X}
- X
- Xspat_free(spat)
- Xregister SPAT *spat;
- X{
- X register SPAT *sp;
- X
- X if (spat->spat_runtime)
- X arg_free(spat->spat_runtime);
- X if (spat->spat_repl) {
- X arg_free(spat->spat_repl);
- X }
- X if (spat->spat_short) {
- X str_free(spat->spat_short);
- X }
- X if (spat->spat_regexp) {
- X regfree(spat->spat_regexp);
- X }
- X
- X /* now unlink from spat list */
- X if (spat_root == spat)
- X spat_root = spat->spat_next;
- X else {
- X for (sp = spat_root; sp->spat_next != spat; sp = sp->spat_next) ;
- X sp->spat_next = spat->spat_next;
- X }
- X
- X safefree((char*)spat);
- X}
- X
- X/* Recursively descend a command sequence and push the address of any string
- X * that needs saving on recursion onto the tosave array.
- X */
- X
- Xstatic int
- Xcmd_tosave(cmd)
- Xregister CMD *cmd;
- X{
- X register CMD *head = cmd;
- X
- X while (cmd) {
- X if (cmd->c_spat)
- X spat_tosave(cmd->c_spat);
- X if (cmd->c_expr)
- X arg_tosave(cmd->c_expr);
- 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 cmd_tosave(cmd->ucmd.ccmd.cc_true);
- X if (cmd->c_type == C_IF && cmd->ucmd.ccmd.cc_alt)
- X cmd_tosave(cmd->ucmd.ccmd.cc_alt);
- X break;
- X case C_EXPR:
- X if (cmd->ucmd.acmd.ac_expr)
- X arg_tosave(cmd->ucmd.acmd.ac_expr);
- X break;
- X }
- X cmd = cmd->c_next;
- X if (cmd && cmd == head) /* reached end of while loop */
- X break;
- X }
- X}
- X
- Xstatic int
- Xarg_tosave(arg)
- Xregister ARG *arg;
- X{
- X register int i;
- X int saving = FALSE;
- X
- X for (i = 1; i <= arg->arg_len; i++) {
- X switch (arg[i].arg_type) {
- X case A_NULL:
- X break;
- X case A_LEXPR:
- X case A_EXPR:
- X saving |= arg_tosave(arg[i].arg_ptr.arg_arg);
- X break;
- X case A_CMD:
- X cmd_tosave(arg[i].arg_ptr.arg_cmd);
- X saving = TRUE; /* assume hanky panky */
- X break;
- X case A_WORD:
- X case A_STAB:
- X case A_LVAL:
- X case A_READ:
- X case A_GLOB:
- X case A_ARYLEN:
- X case A_SINGLE:
- X case A_DOUBLE:
- X case A_BACKTICK:
- X break;
- X case A_SPAT:
- X saving |= spat_tosave(arg[i].arg_ptr.arg_spat);
- X break;
- X case A_NUMBER:
- X break;
- X }
- X }
- X switch (arg->arg_type) {
- X case O_EVAL:
- X case O_SUBR:
- X saving = TRUE;
- X }
- X if (saving)
- X apush(tosave,arg->arg_ptr.arg_str);
- X return saving;
- X}
- X
- Xstatic int
- Xspat_tosave(spat)
- Xregister SPAT *spat;
- X{
- X int saving = FALSE;
- X
- X if (spat->spat_runtime)
- X saving |= arg_tosave(spat->spat_runtime);
- X if (spat->spat_repl) {
- X saving |= arg_tosave(spat->spat_repl);
- X }
- X
- X return saving;
- X}
- !STUFFY!FUNK!
- echo Extracting x2p/Makefile.SH
- sed >x2p/Makefile.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
- X . ./config.sh
- X ;;
- Xesac
- Xcase "$0" in
- X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
- Xesac
- Xcase "$mallocsrc" in
- X'') ;;
- X*) mallocsrc="../$mallocsrc";;
- Xesac
- Xecho "Extracting x2p/Makefile (with variable substitutions)"
- Xcat >Makefile <<!GROK!THIS!
- X# $Header: Makefile.SH,v 2.0 88/06/05 00:15:31 root Exp $
- X#
- X# $Log: Makefile.SH,v $
- X# Revision 2.0 88/06/05 00:15:31 root
- X# Baseline version 2.0.
- X#
- X#
- X
- XCC = $cc
- Xbin = $bin
- Xlib = $lib
- Xmansrc = $mansrc
- Xmanext = $manext
- XCFLAGS = $ccflags -O
- XLDFLAGS = $ldflags
- XSMALL = $small
- XLARGE = $large $split
- Xmallocsrc = $mallocsrc
- Xmallocobj = $mallocobj
- X
- Xlibs = $libnm -lm
- X!GROK!THIS!
- X
- Xcat >>Makefile <<'!NO!SUBS!'
- X
- Xpublic = a2p s2p
- X
- Xprivate =
- X
- Xmanpages = a2p.man s2p.man
- X
- Xutil =
- X
- Xsh = Makefile.SH makedepend.SH
- X
- Xh = EXTERN.h INTERN.h config.h handy.h hash.h a2p.h str.h util.h
- X
- Xc = hash.c $(mallocsrc) str.c util.c walk.c
- X
- Xobj = hash.o $(mallocobj) str.o util.o walk.o
- X
- Xlintflags = -phbvxac
- X
- Xaddedbyconf = Makefile.old bsd eunice filexp loc pdp11 usg v7
- X
- X# grrr
- XSHELL = /bin/sh
- X
- X.c.o:
- X $(CC) -c $(CFLAGS) $(LARGE) $*.c
- X
- Xall: $(public) $(private) $(util)
- X touch all
- X
- Xa2p: $(obj) a2p.o
- X $(CC) $(LDFLAGS) $(LARGE) $(obj) a2p.o $(libs) -o a2p
- X
- Xa2p.c: a2p.y
- X @ echo Expect 103 shift/reduce errors...
- X yacc a2p.y
- X mv y.tab.c a2p.c
- X
- Xa2p.o: a2p.c a2py.c a2p.h EXTERN.h util.h INTERN.h handy.h ../config.h
- X $(CC) -c $(CFLAGS) $(LARGE) a2p.c
- X
- X# if a .h file depends on another .h file...
- X$(h):
- X touch $@
- Xinstall: a2p s2p
- X# won't work with csh
- X export PATH || exit 1
- X - mv $(bin)/a2p $(bin)/a2p.old 2>/dev/null
- X - mv $(bin)/s2p $(bin)/s2p.old
- X - if test `pwd` != $(bin); then cp $(public) $(bin); fi
- X cd $(bin); \
- Xfor pub in $(public); do \
- Xchmod +x `basename $$pub`; \
- Xdone
- X# chmod +x makedir
- X# - ./makedir `filexp $(lib)`
- X# - \
- X#if test `pwd` != `filexp $(lib)`; then \
- X#cp $(private) `filexp $(lib)`; \
- X#fi
- X# cd `filexp $(lib)`; \
- X#for priv in $(private); do \
- X#chmod +x `basename $$priv`; \
- X#done
- X - if test `pwd` != $(mansrc); then \
- Xfor page in $(manpages); do \
- Xcp $$page $(mansrc)/`basename $$page .man`.$(manext); \
- Xdone; \
- Xfi
- X
- Xclean:
- X rm -f *.o
- X
- Xrealclean:
- X rm -f a2p *.orig */*.orig *.o core $(addedbyconf)
- X
- X# The following lint has practically everything turned on. Unfortunately,
- X# you have to wade through a lot of mumbo jumbo that can't be suppressed.
- X# If the source file has a /*NOSTRICT*/ somewhere, ignore the lint message
- X# for that spot.
- X
- Xlint:
- X lint $(lintflags) $(defs) $(c) > a2p.fuzz
- X
- Xdepend: ../makedepend
- X ../makedepend
- X
- Xclist:
- X echo $(c) | tr ' ' '\012' >.clist
- X
- Xhlist:
- X echo $(h) | tr ' ' '\012' >.hlist
- X
- Xshlist:
- X echo $(sh) | tr ' ' '\012' >.shlist
- X
- X# AUTOMATICALLY GENERATED MAKE DEPENDENCIES--PUT NOTHING BELOW THIS LINE
- X$(obj):
- X @ echo "You haven't done a "'"make depend" yet!'; exit 1
- Xmakedepend: makedepend.SH
- X /bin/sh makedepend.SH
- X!NO!SUBS!
- X$eunicefix Makefile
- Xcase `pwd` in
- X*SH)
- X $rm -f ../Makefile
- X ln Makefile ../Makefile
- X ;;
- Xesac
- !STUFFY!FUNK!
- echo Extracting Wishlist
- sed >Wishlist <<'!STUFFY!FUNK!' -e 's/X//'
- Xdate support
- Xcase statement
- Xioctl() support
- Xrandom numbers
- !STUFFY!FUNK!
- echo ""
- echo "End of kit 4 (of 15)"
- cat /dev/null >kit4isdone
- run=''
- config=''
- for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
- if test -f kit${iskit}isdone; then
- run="$run $iskit"
- else
- todo="$todo $iskit"
- fi
- done
- case $todo in
- '')
- echo "You have run all your kits. Please read README and then type Configure."
- chmod 755 Configure
- ;;
- *) echo "You have run$run."
- echo "You still need to run$todo."
- ;;
- esac
- : Someone might mail this, so...
- exit
-
-