📄 e.c
字号:
/* * a small awk clone * * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi * * Absolutely no warranty. Use this software with your own risk. * * Permission to use, copy, modify and distribute this software for any * purpose and without fee is hereby granted, provided that the above * copyright and disclaimer notice. * * This program was written to fit into 64K+64K memory of the Minix 1.2. */#include <stdio.h>#include <ctype.h>#include "awk.h"#include "regexp.h"extern char **FS, **OFS, **ORS, **OFMT;extern double *RSTART, *RLENGTH;extern char record[];extern CELL *field[];extern int r_start, r_length;double getfval(), atof();char *strsave(), *getsval(), *strcat(), *strstr();CELL *mkcell(), *mktmp();CELL *Field(), *Split(), *Forin();CELL *Arith(), *Assign(), *Stat(), *Mathfun(), *Strfun(), *Cond();CELL *Print(), *Cat(), *Array(), *Element();CELL *If(), *While(), *For(), *Do(), *Jump();CELL *P1stat(), *P2stat(), *Print0();CELL *Arg(), *Call(), *Ret();CELL *Subst(), *In(), *Getline(), *Delete(), *Close();CELL *Nulproc(), *Usrfun();CELL *_Arg();FILE *getfp(); /* r.c */CELL truecell = { NUM, NULL, 1.0 };CELL falsecell = { NUM, NULL, 0.0 };static CELL breakcell = { BRK, NULL, 0.0 };static CELL contcell = { CNT, NULL, 0.0 };static CELL nextcell = { NXT, NULL, 0.0 };static CELL retcell = { RTN, NULL, 0.0 };static CELL *retval; /* function return value */int pateval; /* used in P1STAT & P2STAT */static char *r_str; /* STR in 'str ~ STR */static regexp *r_pat; /* compiled pattern for STR */CELL *(*proctab[])() = { Arg, Arith, Array, Assign, Call, Cat, Cond, Delete, Do, Element, Field, For, Forin, Getline, If, In, Jump, Mathfun, Nulproc, P1stat, P2stat, Print, Print0, Strfun, Subst, Usrfun, While};CELL *execute(p) NODE *p;{ int type, i; CELL *r, *(*proc)(); type = p->n_type; if (type == VALUE) { if ((r = (CELL *) p->n_arg[0])->c_type & PAT && pateval) { i = match(r->c_sval, (char *)record) ? 1 : 0; r = mktmp(NUM, NULL, (double) i); } return r; } for ( ; p != NULL; p = p->n_next) {#if 0 if (p->n_type == VALUE) continue; /* neglect */#endif/* switch ((int) p->n_type) { case ARRAY: r = Array(p); break; case ARITH: r = Arith(p); break; case ASSIGN: r = Assign(p); break; case PRINT: r = Print(p); break; case PRINT0: r = Print0(p); break; case CAT: r = Cat(p); break; case MATHFUN: r = Mathfun(p); break; case STRFUN: r = Strfun(p); break; case COND: r = Cond(p); break; case IF: r = If(p); break; case P1STAT: r = P1stat(p); break; case P2STAT: r = P2stat(p); break; case WHILE: r = While(p); break; case DO: r = Do(p); break; case FOR: r = For(p); break; case FORIN: r = Forin(p); break; case FIELD: r = Field(p); break; case JUMP: r = Jump(p); break; case ARG: r = Arg(p); break; case CALL: r = Call(p); break; case SUBST: r = Subst(p); break; case ELEMENT: r = Element(p); break; case IN: r = In(p); break; case GETLINE: r = Getline(p); break; case DELETE: r = Delete(p); break; case NULPROC: r = &truecell; break; default: printf("PROGRAM ERROR ? ILLEGAL NODE TYPE(%d)\n", type); exit(1); break; }*/ i = (int) p->n_type; if (i < FIRSTP || i > LASTP) error("ILLEGAL PROC (%d)", i); proc = proctab[i - FIRSTP]; r = (*proc)(p); if (r->c_type & (BRK|CNT|NXT|RTN)) return r; if (p->n_next != NULL) c_free(r);#ifdef DOS kbhit(); /* needs in MS-DOS */#endif } return r;}static CELL *Arith(p) NODE *p;{ int op; CELL *r, *u, *v, *execute(); double x, y, fmod(), pow(); op = (int) p->n_arg[0]; if (op == UMINUS) { u = execute(p->n_arg[1]); x = - getfval(u); } else if (op == INCDEC) { u = execute(p->n_arg[1]); x = getfval(u); setfval(u, x + (int) p->n_arg[2]); if ((int) p->n_arg[3] == PRE) return u; /* return dummy */ } else { u = execute(p->n_arg[1]); v = execute(p->n_arg[2]); x = getfval(u); y = getfval(v); if (op == DIV || op == MOD) { if (y == 0.0) fprintf(stderr, "divid by 0\n"); } switch (op) { case SUB: x -= y;break; case ADD: x += y; break; case MULT: x *= y; break; case DIV: if (y == 0.0) error("division by zero in \"/\"", (char *)0); x /= y; break; case MOD: if (y == 0.0) error("division by zero in \"%%\"", (char *)0); x = fmod(x, y); break; case POWER: x = pow(x, y); break; default: printf("UNSUPPORTED ARITH OPERATOR !\n"); break; } c_free(v); } c_free(u); r = mktmp(NUM, NULL, x); return r;}static CELL *Assign(p) NODE *p;{ CELL *u, *v, *execute(); int op; double x, y, fmod(), pow(); op = (int) p->n_arg[0]; u = execute(p->n_arg[1]);#if 0 if (u->c_type == UDF) /* fix up local var */ u->c_type |= VAR|STR;#endif if (!(u->c_type & (VAR|FLD|REC)) && (u->c_type != UDF)) fprintf(stderr, "ASSIGN TO NON VARIABLE (%d)\n", u->c_type); v = execute(p->n_arg[2]); if (u == v) goto rtn; /* same node */ if (op == ASSIGN) { if (v->c_type & NUM/* || isnum(v->c_sval)*/) setfval(u, getfval(v)); else setsval(u, getsval(v)); } else { x = getfval(u); y = getfval(v); switch (op) { case ADDEQ: x += y; break; case SUBEQ: x -= y; break; case MULTEQ: x *= y; break; case DIVEQ: if (y == 0.0) error("division by zero in \"/=\"", (char *)0); x /= y; break; case MODEQ: if (y == 0.0) error("division by zero in \"%=\"", (char *)0); x = fmod(x, y); break; case POWEQ: x = pow(x, y); break; default: synerr("illegal assign op (%d)", op); break; } setfval(u, x); }rtn: c_free(v); return u;}static CELL *Cat(p) NODE *p;{ CELL *u; char *s, *t, str[BUFSIZ]; u = execute(p->n_arg[0]); s = getsval(u); for (t = str; *s; ) *t++ = *s++; c_free(u); u = execute(p->n_arg[1]); s = getsval(u); while (*s) *t++ = *s++; c_free(u); *t = '\0'; return mktmp(STR, str, 0.0);}static CELL *Print(p) NODE *p;{ register int i, redir, typ; CELL *u; char *s, str[BUFSIZ]; char *file; FILE *fp; redir = (int) p->n_arg[0]; if (typ = redir & PRMASK) { /* redirect */ u = execute(p->n_arg[1]); file = getsval(u); if (typ == R_PIPE) typ = R_POUT; fp = getfp(file, typ); c_free(u); } else fp = stdout; if (redir & FORMAT) /* format */ format(str, p); else { *str = '\0'; for (i = 2; p->n_arg[i] != NULL; i++) { if (i > 2) strcat(str, *OFS); u = execute(p->n_arg[i]); s = getsval(u); strcat(str, s); c_free(u); } strcat(str, *ORS); } if (redir & STROUT) /* sprintf */ return mktmp(STR, str, 0.0); fputs(str, fp); fflush(fp); return &truecell;}static CELL *Mathfun(p) NODE *p;{ CELL *u, *v; double x, y; double atan2(), cos(), exp(), log(), sin(), sqrt(), modf(); if ((int) p->n_arg[1] == 0) { u = NULL; x = 0.0; } else { u = execute(p->n_arg[2]); x = getfval(u); } switch ((int) p->n_arg[0]) { case ATAN2: if ((int) p->n_arg[1] == 2) { v = execute(p->n_arg[3]); y = getfval(v); x = atan2(x, y); c_free(v); } else x = 0.0; break; case COS: x = cos(x); break; case EXP: x = exp(x); break; case INT: y = modf(x, &x); break; case LOG: x = log(x); break; case SIN: x = sin(x); break; case SQRT: x = sqrt(x); break; case RAND: x = (double) rand() / 32768.0; break; case SRAND: if (x == 0.0) x = (double) time(0); x = (double) srand((int) x); break; default: fprintf(stderr, "unknown math function (%d)\n", p->n_arg[2]); break; } if (u != NULL) c_free(u); return mktmp(NUM, NULL, x);}static CELL *Strfun(p) NODE *p;{ CELL *u, *v, *r; char *s, *t, str[BUFSIZ]; int i, m, n; double x; regexp *pat, *getpat(); n = (int) p->n_arg[1]; if (n > 0 && (int) p->n_arg[0] != SPLIT) { u = execute(p->n_arg[2]); s = getsval(u); } else { s = ""; u = NULL; } switch ((int) p->n_arg[0]) { case INDEX: if (n > 1) { v = execute(p->n_arg[3]); t = getsval(v); i = Index(s, t); c_free(v); } else i = 0; r = mktmp(NUM, NULL, (double) i); break; case LENGTH: i = (n > 0) ? jstrlen(s) : jstrlen(record); r = mktmp(NUM, NULL, (double) i); break; case SPLIT: r = Split(p); break; case SUBSTR: if (n > 1) { v = execute(p->n_arg[3]); m = (int) getfval(v) - 1; c_free(v); } else m = 0; if (n > 2) { v = execute(p->n_arg[4]); n = (int) getfval(v); c_free(v); } else n = jstrlen(s) - m; for (t = str; *s && m-- > 0; s++) if (isKanji(*s)) s++; while (*s && n-- > 0) { if (isKanji(*s)) *t++ = *s++; *t++ = *s++; } *t = '\0'; r = mktmp(STR, str, 0.0); break; case RMATCH: if (n > 1) { v = execute(p->n_arg[3]); pat = getpat(v); match(pat, s); c_free(v); if (r_start) { /* change only if match */ *RSTART = (double) r_start; *RLENGTH = (double) r_length; } r = mktmp(NUM, NULL, (double) r_start); } else error("missing regexpr in match(str, regexpr)"); break; case CLOSE: r = Close(s); break; case SYSTEM: r = mktmp(NUM, NULL, system(s) == -1 ? 0.0 : 1.0); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -