📄 run.c
字号:
void tfree(Cell *a) /* free a tempcell */{ if (freeable(a)) xfree(a->sval); if (a == tmps) ERROR "tempcell list is curdled" FATAL; a->cnext = tmps; tmps = a;}Cell *gettemp(void) /* get a tempcell */{ int i; register Cell *x; if (!tmps) { tmps = (Cell *) calloc(100, sizeof(Cell)); if (!tmps) ERROR "out of space for temporaries" FATAL; 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] ) */{ register Cell *x; register int m; register uchar *s; x = execute(a[0]); m = getfval(x); if (m == 0 && !is_a_number(s = getsval(x))) /* suspicion! */ ERROR "illegal field $(%s), name \"%s\"", s, x->nval FATAL; /* can x->nval ever be null??? */ /* ERROR "illegal field $(%s)", s FATAL; */ tempfree(x); x = fieldadr(m); x->ctype = OCELL; x->csub = CFLD; return(x);}Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */{ register int k, m, n; register uchar *s; int temp; register Cell *x, *y, *z; x = execute(a[0]); y = execute(a[1]); if (a[2] != 0) z = execute(a[2]); s = getsval(x); k = strlen(s) + 1; if (k <= 1) { tempfree(x); tempfree(y); if (a[2] != 0) tempfree(z); x = gettemp(); setsval(x, ""); return(x); } m = getfval(y); if (m <= 0) m = 1; else if (m > k) m = k; tempfree(y); if (a[2] != 0) { n = 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(); temp = s[n+m-1]; /* with thanks to John Linderman */ s[n+m-1] = '\0'; setsval(y, s + m - 1); s[n+m-1] = temp; tempfree(x); return(y);}Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */{ register Cell *x, *y, *z; register uchar *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) (p1 - s1 + 1); /* origin 1 */ break; } } tempfree(x); tempfree(y); setfval(z, v); return(z);}format(uchar *buf, int bufsize, uchar *s, Node *a) /* printf-like conversions */{ uchar fmt[RECSIZE]; register uchar *p, *t, *os; register Cell *x; int flag = 0, n; os = s; p = buf; while (*s) { if (p - buf >= bufsize) return -1; if (*s != '%') { *p++ = *s++; continue; } if (*(s+1) == '%') { *p++ = '%'; s += 2; continue; } for (t=fmt; (*t++ = *s) != '\0'; s++) { if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L') break; /* the ansi panoply */ if (*s == '*') { x = execute(a); a = a->nnext; sprintf((char *)t-1, "%d", (int) getfval(x)); t = fmt + strlen(fmt); tempfree(x); } } *t = '\0'; if (t >= fmt + sizeof(fmt)) ERROR "format item %.30s... too long", os FATAL; 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: ERROR "weird printf conversion %s", fmt WARNING; flag = 0; break; } if (a == NULL) ERROR "not enough args in printf(%s)", os FATAL; x = execute(a); a = a->nnext; switch (flag) { case 0: sprintf((char *)p, "%s", fmt); /* unknown, so dump it too */ p += strlen(p); sprintf((char *)p, "%s", getsval(x)); break; case 1: sprintf((char *)p, (char *)fmt, getfval(x)); break; case 2: sprintf((char *)p, (char *)fmt, (long) getfval(x)); break; case 3: sprintf((char *)p, (char *)fmt, (int) getfval(x)); break; case 4: t = getsval(x); n = strlen(t); if (n >= bufsize) ERROR "huge string (%d chars) in printf %.30s...", n, t FATAL; sprintf((char *)p, (char *)fmt, t); break; case 5: isnum(x) ? sprintf((char *)p, (char *)fmt, (int) getfval(x)) : sprintf((char *)p, (char *)fmt, getsval(x)[0]); break; } tempfree(x); p += strlen(p); s++; } *p = '\0'; for ( ; a; a = a->nnext) /* evaluate any remaining args */ execute(a); return 0;}Cell *asprintf(Node **a, int n) /* sprintf(a[0]) */{ register Cell *x; register Node *y; uchar buf[3*RECSIZE]; y = a[0]->nnext; x = execute(a[0]); if (format(buf, sizeof buf, getsval(x), y) == -1) ERROR "sprintf string %.30s... too long", buf FATAL; tempfree(x); x = gettemp(); x->sval = tostring(buf); x->tval = STR; return(x);}Cell *aprintf(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; register Cell *x; register Node *y; uchar buf[3*RECSIZE]; y = a[0]->nnext; x = execute(a[0]); if (format(buf, sizeof buf, getsval(x), y) == -1) ERROR "printf string %.30s... too long", buf FATAL; tempfree(x); if (a[1] == NULL) { fputs((char *)buf, stdout); if (ferror(stdout)) ERROR "write error on stdout" FATAL; } else { fp = redirect((int)a[1], a[2]); fputs((char *)buf, fp); fflush(fp); if (ferror(fp)) ERROR "write error on %s", filename(fp) FATAL; } return(true);}Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */{ Awkfloat i, j; double v; register 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) ERROR "division by zero" FATAL; i /= j; break; case MOD: if (j == 0) ERROR "division by zero in mod" FATAL; 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 */ ERROR "illegal arithmetic operator %d", n FATAL; } 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. */{ register Cell *x, *z; register 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. */ register 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 (y->tval & STR) setsval(x, getsval(y)); else if (y->tval & NUM) 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) ERROR "division by zero in /=" FATAL; xf /= yf; break; case MODEQ: if (yf == 0) ERROR "division by zero in %%=" FATAL; 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: ERROR "illegal assignment operator %d", n FATAL; break; } tempfree(y); setfval(x, xf); return(x);}Cell *cat(Node **a, int q) /* a[0] cat a[1] */{ register Cell *x, *y, *z; register int n1, n2; register uchar *s; x = execute(a[0]); y = execute(a[1]); getsval(x); getsval(y); n1 = strlen(x->sval); n2 = strlen(y->sval); s = (uchar *) malloc(n1 + n2 + 1); if (s == NULL) ERROR "out of space concatenating %.15s... and %.15s...", x->sval, y->sval FATAL; 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] } */{ register 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] } */{ register Cell *x; register int pair; pair = (int) 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, *y, *ap; register uchar *s; register int sep; uchar *t, temp, num[10], *fs; int n, tempstat; y = execute(a[0]); /* source string */ s = getsval(y); if (a[2] == 0) /* fs string */ fs = *FS; else if ((int) a[3] == STRING) { /* split(str,arr,"string") */ x = execute(a[2]); fs = getsval(x); } else if ((int) a[3] == REGEXPR) fs = (uchar*) "(regexpr)"; /* split(str,arr,/regexpr/) */ else ERROR "illegal type of split()" FATAL; 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 = (uchar *) makesymtab(NSYMTAB); n = 0; if (*s != '\0' && strlen(fs) > 1 || (int) a[3] == REGEXPR) { /* reg expr */ fa *pfa; if ((int) a[3] == REGEXPR) { /* it's ready already */ pfa = (fa *) a[2]; } else { pfa = makedfa(fs, 1); } if (nematch(pfa,s)) { tempstat = pfa->initstat; pfa->initstat = 2; do { n++; sprintf((char *)num, "%d", n); temp = *patbeg; *patbeg = '\0'; if (is_a_number(s)) setsymtab(num, s, atof((char *)s), STR|NUM, (Array *) ap->sval); else setsymtab(num, s, 0.0, STR, (Array *) ap->sval); *patbeg = temp; s = patbeg + patlen; if (*(patbeg+patlen-1) == 0 || *s == 0) { n++; sprintf((char *)num, "%d", n); setsymtab(num, "", 0.0, STR, (Array *) ap->sval); pfa->initstat = tempstat; goto spdone; } } while (nematch(pfa,s)); } n++; sprintf((char *)num, "%d", n); if (is_a_number(s)) setsymtab(num, s, atof((char *)s), STR|NUM, (Array *) ap->sval); else setsymtab(num, s, 0.0, STR, (Array *) ap->sval); spdone: pfa = NULL; } else if (sep == ' ') { for (n = 0; ; ) { while (*s == ' ' || *s == '\t' || *s == '\n') s++; if (*s == 0) break; n++; t = s; do s++; while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0'); temp = *s; *s = '\0'; sprintf((char *)num, "%d", n); if (is_a_number(t)) setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval); else setsymtab(num, t, 0.0, STR, (Array *) ap->sval); *s = temp; if (*s != 0) s++; } } else if (*s != 0) { for (;;) { n++; t = s; while (*s != sep && *s != '\n' && *s != '\0') s++; temp = *s; *s = '\0'; sprintf((char *)num, "%d", n); if (is_a_number(t)) setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval); else setsymtab(num, t, 0.0, STR, (Array *) ap->sval); *s = temp; if (*s++ == 0) break; } } tempfree(ap); tempfree(y); if (a[2] != 0 && (int) a[3] == STRING) tempfree(x); x = gettemp(); x->tval = NUM;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -