|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 9218 (0x2402) Types: TextFile Notes: UNIX file Names: »awk3.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─⟦this⟧ »cmd/awk/awk3.c«
/* * AWK * Part 3 - execution of the compiled code. */ #include "awk.h" #include "y.tab.h" static char *sb; /* String beginning -- evalre */ static char toodeep[] = "For/while nesting too deep"; char *reexec(); /* * Called for each input file * Also, called before the first file * and after the last file. * This routine executes the code for * each input line. */ awk(np, fp, fn) register NODE *np; register FILE *fp; char *fn; { char ibuf[MAXRECORD]; sassign(FILENAMEp, fn); if (fp == NULL) { lineno = 0; execute(np, NULL); } else { if (fp != stdin) setbuf(fp, inbuf); lineno = 1; setjmp(nextenv); while (awkinput(ibuf, MAXRECORD, fp) != NULL) { iassign(NRp, NRp->t_INT+1); execute(np, ibuf); } if (fp != stdin) fclose(fp); } } /* * Read a record in for * awk. */ STRING awkinput(as, lim, fp) STRING as; unsigned lim; register FILE *fp; { register int c; register unsigned char *s; register int rs; register STRING ret; register int nf = 0; register int spcflag = 0; if ((rs = RS[0]) == '\0') { rs = '\n'; spcflag++; } s = as; while (--lim>0 && (c = getc(fp))!=EOF) { if (c == '\n') lineno++; if (c == rs) if (!spcflag || s==as || s[-1]=='\n') break; *s++ = c; } *s = '\0'; ret = c==EOF && s==as ? NULL : as; s = as; for (;;) { while (FSMAP[*s]) s++; if (*s == '\0') break; nf++; while ((c = *s++)!='\0' && !FSMAP[c]) ; if (c == '\0') break; } iassign(NFp, (INT)nf); return (ret); } /* * This is the root of the execution tree * that handles patterns and actions * and lists of the above. * `s' is the input string. * Free all outstanding nodes accumulated * during execution at the end of this * routine (each input line). */ execute(np, s) register NODE *np; register STRING s; { register NODE *xp; inline = s; while (np != NULL) { if (np->n_op == ALIST) { xp = np->n_O1; np = np->n_O2; } else { xp = np; np = NULL; } if (xp->n_op != AROOT) awkerr("Bad op in execute %d", xp->n_op); if (xp->n_O1 != NULL) { if (evalpat(xp->n_O1)) if (xp->n_O2 == NULL) { if (!beginflag && !endflag) xprint(&xfield0, NULL); } else evalact(xp->n_O2); } else if (!beginflag && !endflag) evalact(xp->n_O2); } while ((np = tempnodes) != NULL) { tempnodes = np->t_next; freenode(np); } if (inline != s) free(inline); } /* * Evaluate the pattern half * of the expression. */ evalpat(np) register NODE *np; { register int ret = 0; if ((beginflag && np->n_op==ABEGIN) || (endflag && np->n_op==AEND)) return (1); if (beginflag || endflag) return (0); switch (np->n_op) { case ABEGIN: case AEND: return (0); case ARANGE: if (np->n_flag==0 && evalpat(np->n_O1)) { np->n_flag++; ret = 1; } else if (np->n_flag == 1) { if (evalpat(np->n_O2)) np->n_flag = 0; ret = 1; } break; default: ret = evalint(np); break; } return (ret); } /* * Evaluate the action part of the * statement. */ evalact(anp) register NODE *anp; { register NODE *np; register int i; again: if (anp == NULL) return; if (anp->n_op == ALIST) { np = anp->n_O1; anp = anp->n_O2; } else { np = anp; anp = NULL; } switch (np->n_op) { case AIF: if (evalint(np->n_O1) != 0) evalact(np->n_O2); else if (np->n_O3 != NULL) evalact(np->n_O3); break; case AWHILE: if (++fwlevel >= NNEST) awkerr(toodeep); while (evalint(np->n_O1) != 0) { if ((i = setjmp(fwenv[fwlevel])) == ABREAK) break; else if (i == ACONTIN) continue; evalact(np->n_O2); } fwlevel--; break; case AFOR: if (++fwlevel >= NNEST) awkerr(toodeep); for (evalact(np->n_O1); evalint(np->n_O2); evalact(np->n_O3)) { if ((i = setjmp(fwenv[fwlevel])) == ABREAK) break; else if (i == ACONTIN) continue; evalact(np->n_O4); } fwlevel--; break; case AFORIN: if (++fwlevel >= NNEST) awkerr(toodeep); xforin(np->n_O1, np->n_O2, np->n_O3); fwlevel--; break; case ABREAK: case ACONTIN: i = np->n_op; if (fwlevel < 0) awkwarn("No for or while for %s", i==ABREAK ? "break" : "continue"); else longjmp(fwenv[fwlevel], i); break; case ANEXT: longjmp(nextenv, 1); break; case AEXIT: if (!exitflag) awkexit(0); break; case APRINT: xprint(np->n_O1, np->n_O2); break; case APRINTF: xprintf(np->n_O1, np->n_O2, NULL); break; default: evalexpr(np); } while ((np = tempnodes) != NULL) { tempnodes = np->t_next; freenode(np); } goto again; } /* * Evaluate an expression. */ NODE * evalexpr(np) register NODE *np; { register NODE *tnp; register int i; switch (np->n_op) { case ATERM: break; case AARRAY: np = xarray(np->n_O1, np->n_O2); break; case AFIELD: np = xfield((int)evalint(np->n_O1), NULL); break; case AFUNC: i = fnargs(tnp = np->n_O2); np = np->n_O1; if (i<np->t_MINARG || (np->t_MAXARG!=-1 && i>np->t_MAXARG)) awkerr("Too %s arguments: %s", i<np->t_MINARG ? "few" : "many", np->t_name); np = (*np->t_FUNC)(tnp, i); break; case AREMAT: case ARENMAT: i = evalre(np->n_O2, evalstring(np->n_O1)); if (np->n_op == ARENMAT) i = !i; np = inode((INT)i); break; case ARE: np = inode((INT)evalre(np->n_O1, inline)); break; case ACONC: np = xconc(np->n_O1, np->n_O2); break; case AADD: np = xadd(evalexpr(np->n_O1), evalexpr(np->n_O2)); break; case ASUB: np = xsub(evalexpr(np->n_O1), evalexpr(np->n_O2)); break; case AMUL: np = xmul(evalexpr(np->n_O1), evalexpr(np->n_O2)); break; case ADIV: np = xdiv(evalexpr(np->n_O1), evalexpr(np->n_O2)); break; case AMOD: np = xmod(evalexpr(np->n_O1), evalexpr(np->n_O2)); break; case AEQ: case ANE: case AGT: case AGE: case ALT: case ALE: np = xcmp(np->n_O1, np->n_O2, np->n_op); break; case AOROR: np = inode((INT)(evalint(np->n_O1) || evalint(np->n_O2))); break; case AANDAND: np = inode((INT)(evalint(np->n_O1) && evalint(np->n_O2))); break; case ANOT: np = inode((INT)(!evalint(np->n_O1))); break; case AASGN: np = xassign(np->n_O1, evalexpr(np->n_O2)); break; case AINCA: np = xinca(np->n_O1); break; case ADECA: np = xdeca(np->n_O1); break; default: awkerr("Bad op in evalexpr %d", np->n_op); } return (np); } /* * Evaluate an expression and * return the resultant string. */ char * evalstring(np) register NODE *np; { static char numbuf[100]; np = evalexpr(np); if (np->n_flag & T_NUM) { if (np->n_flag & T_INT) return (sprintf(numbuf, "%D", np->t_INT)); else return (sprintf(numbuf, "%.6g", np->t_FLOAT)); } else return (np->t_STRING); } /* * Evaluate an expression and * return the resultant INT. */ INT evalint(np) register NODE *np; { np = evalexpr(np); if (np->n_flag & T_NUM) { if (np->n_flag & T_INT) return (np->t_INT); else return (np->t_FLOAT); } else return (stoi(np->t_STRING)); } /* * Evaluate an expression and * return the resultant FLOAT. */ FLOAT evalfloat(np) register NODE *np; { np = evalexpr(np); if (np->n_flag & T_NUM) { if (np->n_flag & T_INT) return (np->t_INT); else return (np->t_FLOAT); } else return (stof(np->t_STRING)); } /* * Called to evaluate a regular expression * with the given string. */ evalre(np, s) register NODE *np; register char *s; { sb = s; if (np!=NULL && np->n_op==ARBOL) return(reexec(np, s) != NULL); s--; do { if (reexec(np, ++s) != NULL) return (1); } while (*s!='\n' && *s!='\0'); return (0); } /* * Internal regular expression * execution routines */ char * reexec(np, s) register NODE *np; register char *s; { register c; register char *ss, *es; for ( ; np != NULL; np = np->n_O3) switch (np->n_op) { case ARBOL: if (s != sb) return (NULL); break; case AREOL: if (*s!='\n' && *s!='\0') return (NULL); break; case ARANY: c = *s++; if (c=='\n' || c=='\0') return (NULL); break; case ARDCHAR: if (islower(np->n_o1.n_char)) { if (isupper(c = *s++)) c = tolower(c); if (c != np->n_o1.n_char) return (NULL); break; } case ARCHAR: c = *s++; if (c != np->n_o1.n_char) return (NULL); break; case ARDCLASS: if (isupper(c = *s++)) c = tolower(c); if ((np->n_o1.n_charp[c/NBPC] & (1<<(c%NBPC))) == 0) return (NULL); break; case ARCLASS: c = *s++; if ((np->n_o1.n_charp[c/NBPC] & (1<<(c%NBPC))) == 0) return (NULL); break; case AROR: ss = s; if ((s = reexec(np->n_O1, s)) == NULL) if ((s = reexec(np->n_O2, ss))==NULL) return (NULL); break; case ARCLOS: ss = s; while ((es = reexec(np->n_O1, s)) != NULL) s = es; while (s >= ss) if ((es = reexec(np->n_O3, s--))!=NULL) return(es); return (NULL); case ARNECL: ss = s; while ((es = reexec(np->n_O1, s)) != NULL) s = es; while (s > ss) if ((es = reexec(np->n_O3, s--))!=NULL) return (es); return (NULL); case ARZOCL: ss = s; if ((es = reexec(np->n_O1, s)) != NULL) s = es; while (s >= ss) if ((es = reexec(np->n_O3, s--))!=NULL) return (es); return (NULL); default: awkerr("RE bad op %d", np->n_op); } return (s); }