📄 run.c
字号:
x->fval = n; return(x);}Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */{ register Cell *x; x = execute(a[0]); if (istrue(x)) { tempfree(x); x = execute(a[1]); } else { tempfree(x); x = execute(a[2]); } return(x);}Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */{ register Cell *x; x = execute(a[0]); if (istrue(x)) { tempfree(x); x = execute(a[1]); } else if (a[2] != 0) { tempfree(x); x = execute(a[2]); } return(x);}Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */{ register Cell *x; for (;;) { x = execute(a[0]); if (!istrue(x)) return(x); tempfree(x); x = execute(a[1]); if (isbreak(x)) { x = true; return(x); } if (isnext(x) || isexit(x) || isret(x)) return(x); tempfree(x); }}Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */{ register Cell *x; for (;;) { x = execute(a[0]); if (isbreak(x)) return true; if (isnext(x) || isexit(x) || isret(x)) return(x); tempfree(x); x = execute(a[1]); if (!istrue(x)) return(x); tempfree(x); }}Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */{ register Cell *x; x = execute(a[0]); tempfree(x); for (;;) { if (a[1]!=0) { x = execute(a[1]); if (!istrue(x)) return(x); else tempfree(x); } x = execute(a[3]); if (isbreak(x)) /* turn off break */ return true; if (isnext(x) || isexit(x) || isret(x)) return(x); tempfree(x); x = execute(a[2]); tempfree(x); }}Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */{ register Cell *x, *vp, *arrayp, *cp, *ncp; Array *tp; int i; vp = execute(a[0]); arrayp = execute(a[1]); if (!isarr(arrayp)) { return true; } tp = (Array *) arrayp->sval; tempfree(arrayp); for (i = 0; i < tp->size; i++) { /* this routine knows too much */ for (cp = tp->tab[i]; cp != NULL; cp = ncp) { setsval(vp, cp->nval); ncp = cp->cnext; x = execute(a[2]); if (isbreak(x)) { tempfree(vp); return true; } if (isnext(x) || isexit(x) || isret(x)) { tempfree(vp); return(x); } tempfree(x); } } return true;}/* if someone ever wants to run over the arrays in sorted order, *//* here it is. but it will likely run slower, not faster. *//* *int qstrcmp(p, q) * uchar **p, **q; *{ * return strcmp(*p, *q); *} *//*Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] *//*{/* register Cell *x, *vp, *arrayp, *cp, *ncp, *ret;/* Array *tp;/* int i, ne;/*#define BIGENOUGH 1000/* uchar *elems[BIGENOUGH], **ep;/*/* vp = execute(a[0]);/* arrayp = execute(a[1]);/* if (!isarr(arrayp))/* ERROR "%s is not an array", arrayp->nval FATAL;/* tp = (Array *) arrayp->sval;/* tempfree(arrayp);/* ep = elems;/* ret = true;/* if (tp->nelem >= BIGENOUGH)/* ep = (uchar **) malloc(tp->nelem * sizeof(char *));/*/* for (i = ne = 0; i < tp->size; i++)/* for (cp = tp->tab[i]; cp != NULL; cp = cp->cnext)/* ep[ne++] = cp->nval;/* if (ne != tp->nelem)/* ERROR "can't happen: lost elems %d vs. %d", ne, tp->nelem FATAL;/* qsort(ep, ne, sizeof(char *), qstrcmp);/* for (i = 0; i < ne; i++) {/* setsval(vp, ep[i]);/* x = execute(a[2]);/* if (isbreak(x)) {/* tempfree(vp);/* break;/* }/* if (isnext(x) || isexit(x) || isret(x)) {/* tempfree(vp);/* ret = x;/* break;/* }/* tempfree(x);/* }/* if (ep != elems)/* free(ep);/* return ret;/*}*/Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */{ register Cell *x, *y; Awkfloat u; register int t; uchar *p, buf[RECSIZE]; Node *nextarg; FILE *fp; t = (int) a[0]; x = execute(a[1]); nextarg = a[1]->nnext; switch (t) { case FLENGTH: u = strlen(getsval(x)); break; case FLOG: u = errcheck(log(getfval(x)), "log"); break; case FINT: modf(getfval(x), &u); break; case FEXP: u = errcheck(exp(getfval(x)), "exp"); break; case FSQRT: u = errcheck(sqrt(getfval(x)), "sqrt"); break; case FSIN: u = sin(getfval(x)); break; case FCOS: u = cos(getfval(x)); break; case FATAN: if (nextarg == 0) { ERROR "atan2 requires two arguments; returning 1.0" WARNING; u = 1.0; } else { y = execute(a[1]->nnext); u = atan2(getfval(x), getfval(y)); tempfree(y); nextarg = nextarg->nnext; } break; case FSYSTEM: fflush(stdout); /* in case something is buffered already */ u = (Awkfloat) system((char *)getsval(x)) / 256; /* 256 is unix-dep */ break; case FRAND: /* in principle, rand() returns something in 0..RAND_MAX */ u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX; break; case FSRAND: if (x->tval & REC) /* no argument provided */ u = time((long *)0); else u = getfval(x); srand((int) u); u = (int) u; break; case FTOUPPER: case FTOLOWER: strcpy(buf, getsval(x)); if (t == FTOUPPER) { for (p = buf; *p; p++) if (islower(*p)) *p = toupper(*p); } else { for (p = buf; *p; p++) if (isupper(*p)) *p = tolower(*p); } tempfree(x); x = gettemp(); setsval(x, buf); return x; case FFLUSH: if ((fp = openfile(GT, getsval(x))) == NULL) u = EOF; else u = fflush(fp); break; default: /* can't happen */ ERROR "illegal function type %d", t FATAL; break; } tempfree(x); x = gettemp(); setfval(x, u); if (nextarg != 0) { ERROR "warning: function has too many arguments" WARNING; for ( ; nextarg; nextarg = nextarg->nnext) execute(nextarg); } return(x);}Cell *printstat(Node **a, int n) /* print a[0] */{ register Node *x; register Cell *y; FILE *fp; if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */ fp = stdout; else fp = redirect((int)a[1], a[2]); for (x = a[0]; x != NULL; x = x->nnext) { y = execute(x); fputs((char *)getsval(y), fp); tempfree(y); if (x->nnext == NULL) fputs((char *)*ORS, fp); else fputs((char *)*OFS, fp); } if (a[1] != 0) fflush(fp); if (ferror(fp)) ERROR "write error on %s", filename(fp) FATAL; return(true);}Cell *nullproc(Node **a, int n){ n; a; return 0;}FILE *redirect(int a, Node *b) /* set up all i/o redirections */{ FILE *fp; Cell *x; uchar *fname; x = execute(b); fname = getsval(x); fp = openfile(a, fname); if (fp == NULL) ERROR "can't open file %s", fname FATAL; tempfree(x); return fp;}struct files { FILE *fp; uchar *fname; int mode; /* '|', 'a', 'w' => LE/LT, GT */} files[FOPEN_MAX] ={ { stdin, "/dev/stdin", LT }, /* watch out: don't free this! */ { stdout, "/dev/stdout", GT }, { stderr, "/dev/stderr", GT }};FILE *openfile(int a, uchar *us){ char *s = us; register int i, m; register FILE *fp; if (*s == '\0') ERROR "null file name in print or getline" FATAL; for (i=0; i < FOPEN_MAX; i++) if (files[i].fname && strcmp(s, files[i].fname) == 0) if (a == files[i].mode || a==APPEND && files[i].mode==GT) return files[i].fp; for (i=0; i < FOPEN_MAX; i++) if (files[i].fp == 0) break; if (i >= FOPEN_MAX) ERROR "%s makes too many open files", s FATAL; fflush(stdout); /* force a semblance of order */ m = a; if (a == GT) { fp = fopen(s, "w"); } else if (a == APPEND) { fp = fopen(s, "a"); m = GT; /* so can mix > and >> */ } else if (a == '|') { /* output pipe */ fp = popen(s, "w"); } else if (a == LE) { /* input pipe */ fp = popen(s, "r"); } else if (a == LT) { /* getline <file */ fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */ } else /* can't happen */ ERROR "illegal redirection %d", a FATAL; if (fp != NULL) { files[i].fname = tostring(s); files[i].fp = fp; files[i].mode = m; } return fp;}uchar *filename(FILE *fp){ int i; for (i = 0; i < FOPEN_MAX; i++) if (fp == files[i].fp) return files[i].fname; return "???";}Cell *closefile(Node **a, int n){ register Cell *x; int i, stat; n; x = execute(a[0]); getsval(x); for (i = 0; i < FOPEN_MAX; i++) if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) { if (ferror(files[i].fp)) ERROR "i/o error occurred on %s", files[i].fname WARNING; if (files[i].mode == '|' || files[i].mode == LE) stat = pclose(files[i].fp); else stat = fclose(files[i].fp); if (stat == EOF) ERROR "i/o error occurred closing %s", files[i].fname WARNING; if (i > 2) /* don't do /dev/std... */ xfree(files[i].fname); files[i].fname = NULL; /* watch out for ref thru this */ files[i].fp = NULL; } tempfree(x); return(true);}void closeall(void){ int i, stat; for (i = 0; i < FOPEN_MAX; i++) if (files[i].fp) { if (ferror(files[i].fp)) ERROR "i/o error occurred on %s", files[i].fname WARNING; if (files[i].mode == '|' || files[i].mode == LE) stat = pclose(files[i].fp); else stat = fclose(files[i].fp); if (stat == EOF) ERROR "i/o error occurred while closing %s", files[i].fname WARNING; }}#define SUBSIZE (20 * RECSIZE)Cell *sub(Node **a, int nnn) /* substitute command */{ register uchar *sptr, *pb, *q; register Cell *x, *y, *result; uchar buf[SUBSIZE], *t; fa *pfa; x = execute(a[3]); /* target string */ t = getsval(x); if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ pfa = (fa *) a[1]; /* regular expression */ else { y = execute(a[1]); pfa = makedfa(getsval(y), 1); tempfree(y); } y = execute(a[2]); /* replacement string */ result = false; if (pmatch(pfa, t)) { pb = buf; sptr = t; while (sptr < patbeg) *pb++ = *sptr++; sptr = getsval(y); while (*sptr != 0 && pb < buf + SUBSIZE - 1) if (*sptr == '\\' && *(sptr+1) == '&') { sptr++; /* skip \, */ *pb++ = *sptr++; /* add & */ } else if (*sptr == '&') { sptr++; for (q = patbeg; q < patbeg+patlen; ) *pb++ = *q++; } else *pb++ = *sptr++; *pb = '\0'; if (pb >= buf + SUBSIZE) ERROR "sub() result %30s too big", buf FATAL; sptr = patbeg + patlen; if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) while (*pb++ = *sptr++) ; if (pb >= buf + SUBSIZE) ERROR "sub() result %.30s too big", buf FATAL; setsval(x, buf); result = true;; } tempfree(x); tempfree(y); return result;}Cell *gsub(Node **a, int nnn) /* global substitute */{ register Cell *x, *y; register uchar *rptr, *sptr, *t, *pb; uchar buf[SUBSIZE]; register fa *pfa; int mflag, tempstat, num; mflag = 0; /* if mflag == 0, can replace empty string */ num = 0; x = execute(a[3]); /* target string */ t = getsval(x); if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ pfa = (fa *) a[1]; /* regular expression */ else { y = execute(a[1]); pfa = makedfa(getsval(y), 1); tempfree(y); } y = execute(a[2]); /* replacement string */ if (pmatch(pfa, t)) { tempstat = pfa->initstat; pfa->initstat = 2; pb = buf; rptr = getsval(y); do { /* uchar *p; int i; printf("target string: %s, *patbeg = %o, patlen = %d\n", t, *patbeg, patlen); printf(" match found: "); p=patbeg; for (i=0; i<patlen; i++) printf("%c", *p++); printf("\n"); */ if (patlen == 0 && *patbeg != 0) { /* matched empty string */ if (mflag == 0) { /* can replace empty */ num++; sptr = rptr; while (*sptr != 0 && pb < buf + SUBSIZE-1) if (*sptr == '\\' && *(sptr+1) == '&') { sptr++; *pb++ = *sptr++; } else if (*sptr == '&') { uchar *q; sptr++; for (q = patbeg; q < patbeg+patlen; ) *pb++ = *q++; } else *pb++ = *sptr++; } if (*t == 0) /* at end */ goto done; *pb++ = *t++; if (pb >= buf + SUBSIZE-1) ERROR "gsub() result %.30s too big", buf FATAL; mflag = 0; } else { /* matched nonempty string */ num++; sptr = t; while (sptr < patbeg && pb < buf + SUBSIZE-1) *pb++ = *sptr++; sptr = rptr; while (*sptr != 0 && pb < buf + SUBSIZE-1) if (*sptr == '\\' && *(sptr+1) == '&') { sptr++; *pb++ = *sptr++; } else if (*sptr == '&') { uchar *q; sptr++; for (q = patbeg; q < patbeg+patlen; ) *pb++ = *q++; } else *pb++ = *sptr++; t = patbeg + patlen; if ((*(t-1) == 0) || (*t == 0)) goto done; if (pb >= buf + SUBSIZE-1) ERROR "gsub() result %.30s too big", buf FATAL; mflag = 1; } } while (pmatch(pfa,t)); sptr = t; while (*pb++ = *sptr++) ; done: if (pb >= buf + SUBSIZE-1) ERROR "gsub() result %.30s too big", buf FATAL; *pb = '\0'; setsval(x, buf); pfa->initstat = tempstat; } tempfree(x); tempfree(y); x = gettemp(); x->tval = NUM; x->fval = num; return(x);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -