📄 run.c
字号:
do s++; while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0'); temp = *s; *s = '\0'; 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); *s = temp; if (*s != 0) s++; } } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */ for (n = 0; *s != 0; s++) { char buf[2]; n++; sprintf(num, "%d", n); buf[0] = *s; buf[1] = 0; if (isdigit(buf[0])) setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval); else setsymtab(num, buf, 0.0, STR, (Array *) ap->sval); } } else if (*s != 0) { for (;;) { n++; t = s; while (*s != sep && *s != '\n' && *s != '\0') s++; temp = *s; *s = '\0'; 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); *s = temp; if (*s++ == 0) break; } } tempfree(ap); tempfree(y); if (a[2] != 0 && arg3type == STRING) tempfree(x); x = gettemp(); x->tval = NUM; x->fval = n; return(x);}Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */{ 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] */{ 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] */{ 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]) */{ Cell *x; for (;;) { x = execute(a[0]); if (isbreak(x)) return True; if (isnext(x) || isnextfile(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] */{ 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] */{ 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;}Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */{ Cell *x, *y; Awkfloat u; int t; wchar_t wc; char *p, *buf; char mbc[50]; Node *nextarg; FILE *fp; t = ptoi(a[0]); x = execute(a[1]); nextarg = a[1]->nnext; switch (t) { case FLENGTH: p = getsval(x); u = (Awkfloat) countposn(p, strlen(p)); 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) { WARNING("atan2 requires two arguments; returning 1.0"); 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(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 (isrec(x)) /* no argument provided */ u = time((time_t *)0); else u = getfval(x); srand((unsigned int) u); break; case FTOUPPER: case FTOLOWER: buf = tostring(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); free(buf); return x; case FFLUSH: if ((fp = openfile(FFLUSH, getsval(x))) == NULL) u = EOF; else u = fflush(fp); break; case FUTF: wc = (int)getfval(x); mbc[wctomb(mbc, wc)] = 0; tempfree(x); x = gettemp(); setsval(x, mbc); return x; default: /* can't happen */ FATAL("illegal function type %d", t); break; } tempfree(x); x = gettemp(); setfval(x, u); if (nextarg != 0) { WARNING("warning: function has too many arguments"); for ( ; nextarg; nextarg = nextarg->nnext) execute(nextarg); } return(x);}Cell *printstat(Node **a, int n) /* print a[0] */{ int r; Node *x; Cell *y; FILE *fp; if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */ fp = stdout; else fp = redirect(ptoi(a[1]), a[2]); for (x = a[0]; x != NULL; x = x->nnext) { y = execute(x); fputs(getsval(y), fp); tempfree(y); if (x->nnext == NULL) r = fputs(*ORS, fp); else r = fputs(*OFS, fp); if (r == EOF) FATAL("write error on %s", filename(fp)); } if (a[1] != 0) if (fflush(fp) == EOF) FATAL("write error on %s", filename(fp)); return(True);}Cell *nullproc(Node **a, int n){ n = n; a = a; return 0;}FILE *redirect(int a, Node *b) /* set up all i/o redirections */{ FILE *fp; Cell *x; char *fname; x = execute(b); fname = getsval(x); fp = openfile(a, fname); if (fp == NULL) FATAL("can't open file %s", fname); tempfree(x); return fp;}struct files { FILE *fp; char *fname; int mode; /* '|', 'a', 'w' => LE/LT, GT */} files[FOPEN_MAX] ={ { NULL, "/dev/stdin", LT }, /* watch out: don't free this! */ { NULL, "/dev/stdout", GT }, { NULL, "/dev/stderr", GT }};void stdinit(void) /* in case stdin, etc., are not constants */{ files[0].fp = stdin; files[1].fp = stdout; files[2].fp = stderr;}FILE *openfile(int a, char *us){ char *s = us; int i, m; FILE *fp = 0; if (*s == '\0') FATAL("null file name in print or getline"); 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; if (a == FFLUSH) return files[i].fp; } if (a == FFLUSH) /* didn't find it, so don't create it! */ return NULL; for (i=0; i < FOPEN_MAX; i++) if (files[i].fp == 0) break; if (i >= FOPEN_MAX) FATAL("%s makes too many open files", s); 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 */ FATAL("illegal redirection %d", a); if (fp != NULL) { files[i].fname = tostring(s); files[i].fp = fp; files[i].mode = m; } return fp;}char *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){ Cell *x; int i, stat; n = 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)) WARNING( "i/o error occurred on %s", files[i].fname ); if (files[i].mode == '|' || files[i].mode == LE) stat = pclose(files[i].fp); else stat = fclose(files[i].fp); if (stat == EOF) WARNING( "i/o error occurred closing %s", files[i].fname ); 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)) WARNING( "i/o error occurred on %s", files[i].fname ); if (files[i].mode == '|' || files[i].mode == LE) stat = pclose(files[i].fp); else stat = fclose(files[i].fp); if (stat == EOF) WARNING( "i/o error occurred while closing %s", files[i].fname ); }}void backsub(char **pb_ptr, char **sptr_ptr);Cell *sub(Node **a, int nnn) /* substitute command */{ char *sptr, *pb, *q; Cell *x, *y, *result; char *t, *buf; void *p; int bufsz = recsize; if ((buf = (char *) malloc(bufsz)) == NULL) FATAL("out of memory in sub"); x = execute(a[3]); /* target string */ t = getsval(x); if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ p = (void *) a[1]; /* regular expression */ else { y = execute(a[1]); p = compre(getsval(y)); tempfree(y); } y = execute(a[2]); /* replacement string */ result = False; if (pmatch(p, t, t)) { sptr = t; adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub"); pb = buf; while (sptr < patbeg) *pb++ = *sptr++; sptr = getsval(y); while (*sptr != 0) { adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub"); if (*sptr == '\\') { backsub(&pb, &sptr); } else if (*sptr == '&') { sptr++; adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub"); for (q = patbeg; q < patbeg+patlen; ) *pb++ = *q++; } else *pb++ = *sptr++; } *pb = '\0'; if (pb > buf + bufsz) FATAL("sub result1 %.30s too big; can't happen", buf); sptr = patbeg + patlen; if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) { adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub"); while ((*pb++ = *sptr++) != 0) ; } if (pb > buf + bufsz) FATAL("sub result2 %.30s too big; can't happen", buf); setsval(x, buf); /* BUG: should be able to avoid copy */ result = True;; } tempfree(x); tempfree(y); free(buf); return result;}Cell *gsub(Node **a, int nnn) /* global substitute */{ Cell *x, *y; char *rptr, *sptr, *t, *pb, *c; char *buf; void *p; int mflag, num; int bufsz = recsize; if ((buf = (char *)malloc(bufsz)) == NULL) FATAL("out of memory in gsub"); mflag = 0; /* if mflag == 0, can replace empty string */ num = 0; x = execute(a[3]); /* target string */ c = t = getsval(x); if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ p = (void *) a[1]; /* regular expression */ else { y = execute(a[1]); p = compre(getsval(y)); tempfree(y); } y = execute(a[2]); /* replacement string */ if (pmatch(p, t, c)) { pb = buf; rptr = getsval(y); do { if (patlen == 0 && *patbeg != 0) { /* matched empty string */ if (mflag == 0) { /* can replace empty */ num++; sptr = rptr; while (*sptr != 0) { adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); if (*sptr == '\\') { backsub(&pb, &sptr); } else if (*sptr == '&') { char *q; sptr++; adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); for (q = patbeg; q < patbeg+patlen; ) *pb++ = *q++; } else *pb++ = *sptr++; } } if (*c == 0) /* at end */ goto done; adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub"); *pb++ = *c++; if (pb > buf + bufsz) /* BUG: not sure of this test */ FATAL("gsub result0 %.30s too big; can't happen", buf); mflag = 0; } else { /* matched nonempty string */ num++; sptr = c; adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub"); while (sptr < patbeg) *pb++ = *sptr++; sptr = rptr; while (*sptr != 0) { adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); if (*sptr == '\\') { backsub(&pb, &sptr); } else if (*sptr == '&') { char *q; sptr++; adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); for (q = patbeg; q < patbeg+patlen; ) *pb++ = *q++; } else *pb++ = *sptr++; } c = patbeg + patlen; if ((c[-1] == 0) || (*c == 0)) goto done; if (pb > buf + bufsz) FATAL("gsub result1 %.30s too big; can't happen", buf); mflag = 1; } } while (pmatch(p, t, c)); sptr = c; adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub"); while ((*pb++ = *sptr++) != 0) ; done: if (pb > buf + bufsz) FATAL("gsub result2 %.30s too big; can't happen", buf); *pb = '\0'; setsval(x, buf); /* BUG: should be able to avoid copy + free */ } tempfree(x); tempfree(y); x = gettemp(); x->tval = NUM; x->fval = num; free(buf); return(x);}void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */{ /* sptr[0] == '\\' */ char *pb = *pb_ptr, *sptr = *sptr_ptr; if (sptr[1] == '\\') { if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */ *pb++ = '\\'; *pb++ = '&'; sptr += 4; } else if (sptr[2] == '&') { /* \\& -> \ + matched */ *pb++ = '\\'; sptr += 2; } else { /* \\x -> \\x */ *pb++ = *sptr++; *pb++ = *sptr++; } } else if (sptr[1] == '&') { /* literal & */ sptr++; *pb++ = *sptr++; } else /* literal \ */ *pb++ = *sptr++; *pb_ptr = pb; *sptr_ptr = sptr;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -