📄 run.c
字号:
{ int i; Cell *x, *y; Awkfloat j; x = execute(a[0]); y = execute(a[1]); if (x->tval&NUM && y->tval&NUM) { j = x->fval - y->fval; i = j<0? -1: (j>0? 1: 0); } else { i = strcmp(getsval(x), getsval(y)); } tempfree(x); tempfree(y); switch (n) { case LT: if (i<0) return(True); else return(False); case LE: if (i<=0) return(True); else return(False); case NE: if (i!=0) return(True); else return(False); case EQ: if (i == 0) return(True); else return(False); case GE: if (i>=0) return(True); else return(False); case GT: if (i>0) return(True); else return(False); default: /* can't happen */ FATAL("unknown relational operator %d", n); } return 0; /*NOTREACHED*/}void tfree(Cell *a) /* free a tempcell */{ if (freeable(a)) { dprintf( ("freeing %s %s %o\n", a->nval, a->sval, a->tval) ); xfree(a->sval); } if (a == tmps) FATAL("tempcell list is curdled"); a->cnext = tmps; tmps = a;}Cell *gettemp(void) /* get a tempcell */{ int i; Cell *x; if (!tmps) { tmps = (Cell *) calloc(100, sizeof(Cell)); if (!tmps) FATAL("out of space for temporaries"); for(i = 1; i < 100; i++) tmps[i-1].cnext = &tmps[i]; tmps[i-1].cnext = 0; } x = tmps; tmps = x->cnext; *x = tempcell; return(x);}Cell *indirect(Node **a, int n) /* $( a[0] ) */{ Cell *x; int m; char *s; x = execute(a[0]); m = (int) getfval(x); if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */ FATAL("illegal field $(%s), name \"%s\"", s, x->nval); /* BUG: can x->nval ever be null??? */ tempfree(x); x = fieldadr(m); x->ctype = OCELL; /* BUG? why are these needed? */ x->csub = CFLD; return(x);}Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */{ int k, m, n; char *s, *p; int temp; Cell *x, *y, *z = 0; x = execute(a[0]); y = execute(a[1]); if (a[2] != 0) z = execute(a[2]); s = getsval(x); k = countposn(s, strlen(s)) + 1; if (k <= 1) { tempfree(x); tempfree(y); if (a[2] != 0) tempfree(z); x = gettemp(); setsval(x, ""); return(x); } m = (int) getfval(y); if (m <= 0) m = 1; else if (m > k) m = k; tempfree(y); if (a[2] != 0) { n = (int) getfval(z); tempfree(z); } else n = k - 1; if (n < 0) n = 0; else if (n > k - m) n = k - m; dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) ); y = gettemp(); while (*s && --m) s += mblen(s, k); for (p = s; *p && n--; p += mblen(p, k)) ; temp = *p; /* with thanks to John Linderman */ *p = '\0'; setsval(y, s); *p = temp; tempfree(x); return(y);}Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */{ Cell *x, *y, *z; char *s1, *s2, *p1, *p2, *q; Awkfloat v = 0.0; x = execute(a[0]); s1 = getsval(x); y = execute(a[1]); s2 = getsval(y); z = gettemp(); for (p1 = s1; *p1 != '\0'; p1++) { for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++) ; if (*p2 == '\0') { v = (Awkfloat) countposn(s1, p1-s1) + 1; /* origin 1 */ break; } } tempfree(x); tempfree(y); setfval(z, v); return(z);}#define MAXNUMSIZE 50int format(char **pbuf, int *pbufsize, char *s, Node *a) /* printf-like conversions */{ char *fmt; char *p, *t, *os; Cell *x; int flag = 0, n; int fmtwd; /* format width */ int fmtsz = recsize; char *buf = *pbuf; int bufsize = *pbufsize; os = s; p = buf; if ((fmt = (char *) malloc(fmtsz)) == NULL) FATAL("out of memory in format()"); while (*s) { adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format"); if (*s != '%') { *p++ = *s++; continue; } if (*(s+1) == '%') { *p++ = '%'; s += 2; continue; } /* have to be real careful in case this is a huge number, eg, %100000d */ fmtwd = atoi(s+1); if (fmtwd < 0) fmtwd = -fmtwd; adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); for (t = fmt; (*t++ = *s) != '\0'; s++) { if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, 0)) FATAL("format item %.30s... ran format() out of memory", os); if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L') break; /* the ansi panoply */ if (*s == '*') { x = execute(a); a = a->nnext; sprintf(t-1, "%d", fmtwd=(int) getfval(x)); if (fmtwd < 0) fmtwd = -fmtwd; adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); t = fmt + strlen(fmt); tempfree(x); } } *t = '\0'; if (fmtwd < 0) fmtwd = -fmtwd; adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); switch (*s) { case 'f': case 'e': case 'g': case 'E': case 'G': flag = 1; break; case 'd': case 'i': flag = 2; if(*(s-1) == 'l') break; *(t-1) = 'l'; *t = 'd'; *++t = '\0'; break; case 'o': case 'x': case 'X': case 'u': flag = *(s-1) == 'l' ? 2 : 3; break; case 's': flag = 4; break; case 'c': flag = 5; break; default: WARNING("weird printf conversion %s", fmt); flag = 0; break; } if (a == NULL) FATAL("not enough args in printf(%s)", os); x = execute(a); a = a->nnext; n = MAXNUMSIZE; if (fmtwd > n) n = fmtwd; adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format"); switch (flag) { case 0: sprintf(p, "%s", fmt); /* unknown, so dump it too */ t = getsval(x); n = strlen(t); if (fmtwd > n) n = fmtwd; adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format"); p += strlen(p); sprintf(p, "%s", t); break; case 1: sprintf(p, fmt, getfval(x)); break; case 2: sprintf(p, fmt, (long) getfval(x)); break; case 3: sprintf(p, fmt, (int) getfval(x)); break; case 4: t = getsval(x); n = strlen(t); if (fmtwd > n) n = fmtwd; if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, 0)) FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t); sprintf(p, fmt, t); break; case 5: if (isnum(x)) { if (getfval(x)) sprintf(p, fmt, (int) getfval(x)); else{ *p++ = '\0'; *p = '\0'; } } else sprintf(p, fmt, getsval(x)[0]); break; } tempfree(x); p += strlen(p); s++; } *p = '\0'; free(fmt); for ( ; a; a = a->nnext) /* evaluate any remaining args */ execute(a); *pbuf = buf; *pbufsize = bufsize; return p - buf;}Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */{ Cell *x; Node *y; char *buf; int bufsz=3*recsize; if ((buf = (char *) malloc(bufsz)) == NULL) FATAL("out of memory in awksprintf"); y = a[0]->nnext; x = execute(a[0]); if (format(&buf, &bufsz, getsval(x), y) == -1) FATAL("sprintf string %.30s... too long. can't happen.", buf); tempfree(x); x = gettemp(); x->sval = buf; x->tval = STR; return(x);}Cell *awkprintf(Node **a, int n) /* printf */{ /* a[0] is list of args, starting with format string */ /* a[1] is redirection operator, a[2] is redirection file */ FILE *fp; Cell *x; Node *y; char *buf; int len; int bufsz=3*recsize; if ((buf = (char *) malloc(bufsz)) == NULL) FATAL("out of memory in awkprintf"); y = a[0]->nnext; x = execute(a[0]); if ((len = format(&buf, &bufsz, getsval(x), y)) == -1) FATAL("printf string %.30s... too long. can't happen.", buf); tempfree(x); if (a[1] == NULL) { /* fputs(buf, stdout); */ fwrite(buf, len, 1, stdout); if (ferror(stdout)) FATAL("write error on stdout"); } else { fp = redirect(ptoi(a[1]), a[2]); /* fputs(buf, fp); */ fwrite(buf, len, 1, fp); fflush(fp); if (ferror(fp)) FATAL("write error on %s", filename(fp)); } free(buf); return(True);}Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */{ Awkfloat i, j = 0; double v; Cell *x, *y, *z; x = execute(a[0]); i = getfval(x); tempfree(x); if (n != UMINUS) { y = execute(a[1]); j = getfval(y); tempfree(y); } z = gettemp(); switch (n) { case ADD: i += j; break; case MINUS: i -= j; break; case MULT: i *= j; break; case DIVIDE: if (j == 0) FATAL("division by zero"); i /= j; break; case MOD: if (j == 0) FATAL("division by zero in mod"); modf(i/j, &v); i = i - j * v; break; case UMINUS: i = -i; break; case POWER: if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ i = ipow(i, (int) j); else i = errcheck(pow(i, j), "pow"); break; default: /* can't happen */ FATAL("illegal arithmetic operator %d", n); } setfval(z, i); return(z);}double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */{ double v; if (n <= 0) return 1; v = ipow(x, n/2); if (n % 2 == 0) return v * v; else return x * v * v;}Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */{ Cell *x, *z; int k; Awkfloat xf; x = execute(a[0]); xf = getfval(x); k = (n == PREINCR || n == POSTINCR) ? 1 : -1; if (n == PREINCR || n == PREDECR) { setfval(x, xf + k); return(x); } z = gettemp(); setfval(z, xf); setfval(x, xf + k); tempfree(x); return(z);}Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */{ /* this is subtle; don't muck with it. */ Cell *x, *y; Awkfloat xf, yf; double v; y = execute(a[1]); x = execute(a[0]); if (n == ASSIGN) { /* ordinary assignment */ if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */ ; /* leave alone unless it's a field */ else if ((y->tval & (STR|NUM)) == (STR|NUM)) { setsval(x, getsval(y)); x->fval = getfval(y); x->tval |= NUM; } else if (isstr(y)) setsval(x, getsval(y)); else if (isnum(y)) setfval(x, getfval(y)); else funnyvar(y, "read value of"); tempfree(y); return(x); } xf = getfval(x); yf = getfval(y); switch (n) { case ADDEQ: xf += yf; break; case SUBEQ: xf -= yf; break; case MULTEQ: xf *= yf; break; case DIVEQ: if (yf == 0) FATAL("division by zero in /="); xf /= yf; break; case MODEQ: if (yf == 0) FATAL("division by zero in %%="); modf(xf/yf, &v); xf = xf - yf * v; break; case POWEQ: if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */ xf = ipow(xf, (int) yf); else xf = errcheck(pow(xf, yf), "pow"); break; default: FATAL("illegal assignment operator %d", n); break; } tempfree(y); setfval(x, xf); return(x);}Cell *cat(Node **a, int q) /* a[0] cat a[1] */{ Cell *x, *y, *z; int n1, n2; char *s; x = execute(a[0]); y = execute(a[1]); getsval(x); getsval(y); n1 = strlen(x->sval); n2 = strlen(y->sval); s = (char *) malloc(n1 + n2 + 1); if (s == NULL) FATAL("out of space concatenating %.15s... and %.15s...", x->sval, y->sval); strcpy(s, x->sval); strcpy(s+n1, y->sval); tempfree(y); z = gettemp(); z->sval = s; z->tval = STR; tempfree(x); return(z);}Cell *pastat(Node **a, int n) /* a[0] { a[1] } */{ Cell *x; if (a[0] == 0) x = execute(a[1]); else { x = execute(a[0]); if (istrue(x)) { tempfree(x); x = execute(a[1]); } } return x;}Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */{ Cell *x; int pair; pair = ptoi(a[3]); if (pairstack[pair] == 0) { x = execute(a[0]); if (istrue(x)) pairstack[pair] = 1; tempfree(x); } if (pairstack[pair] == 1) { x = execute(a[1]); if (istrue(x)) pairstack[pair] = 0; tempfree(x); x = execute(a[2]); return(x); } return(False);}Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */{ Cell *x = 0, *y, *ap; char *s; int sep; char *t, temp, num[50], *fs = 0; int n, tempstat, arg3type; y = execute(a[0]); /* source string */ s = getsval(y); arg3type = ptoi(a[3]); if (a[2] == 0) /* fs string */ fs = *FS; else if (arg3type == STRING) { /* split(str,arr,"string") */ x = execute(a[2]); fs = getsval(x); } else if (arg3type == REGEXPR) fs = "(regexpr)"; /* split(str,arr,/regexpr/) */ else FATAL("illegal type of split"); sep = *fs; ap = execute(a[1]); /* array name */ freesymtab(ap); dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) ); ap->tval &= ~STR; ap->tval |= ARR; ap->sval = (char *) makesymtab(NSYMTAB); n = 0; if ((*s != '\0' && strlen(fs) > 1) || arg3type == REGEXPR) { /* reg expr */ void *p; if (arg3type == REGEXPR) { /* it's ready already */ p = (void *) a[2]; } else { p = compre(fs); } t = s; if (nematch(p,s,t)) { do { n++; sprintf(num, "%d", n); temp = *patbeg; *patbeg = '\0'; if (is_number(t)) setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); else setsymtab(num, t, 0.0, STR, (Array *) ap->sval); *patbeg = temp; t = patbeg + patlen; if (t[-1] == 0 || *t == 0) { n++; sprintf(num, "%d", n); setsymtab(num, "", 0.0, STR, (Array *) ap->sval); goto spdone; } } while (nematch(p,s,t)); } n++; sprintf(num, "%d", n); if (is_number(t)) setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); else setsymtab(num, t, 0.0, STR, (Array *) ap->sval); spdone: p = NULL; } else if (sep == ' ') { for (n = 0; ; ) { while (*s == ' ' || *s == '\t' || *s == '\n') s++; if (*s == 0) break; n++; t = s;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -