Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */ { 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 */ ERROR "unknown relational operator %d", n FATAL; } return 0; /*NOTREACHED*/ }
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) 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 *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) (p1 - s1 + 1); /* origin 1 */ break; } } tempfree(x); tempfree(y); setfval(z, v); return(z); }
Cell *sub(Node **a, int nnn) /* substitute command */ { char *sptr, *pb, *q; Cell *x, *y, *result; char *t, *buf; fa *pfa; 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 */ 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)) { 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 *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 *catstr(Cell *a, Cell *b) /* concatenate a and b */ { Cell *c; char *p; char *sa = getsval(a); char *sb = getsval(b); size_t l = strlen(sa) + strlen(sb) + 1; p = malloc(l); if (p == NULL) FATAL("out of space concatenating %s and %s", sa, sb); snprintf(p, l, "%s%s", sa, sb); c = setsymtab(p, p, 0.0, CON|STR|DONTFREE, symtab); free(p); return c; }
Cell *closefile(Node **a, int n) { Cell *x; int i, stat; n = n; x = execute(a[0]); getsval(x); stat = -1; for (i = 0; i < nfiles; 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); x = gettemp(); setfval(x, (Awkfloat) stat); return(x); }
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); }
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 *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 *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ { Cell *x, *y, *z; char *s; Node *np; char buf[RECSIZE]; x = execute(a[0]); /* Cell* for symbol table */ buf[0] = 0; for (np = a[1]; np; np = np->nnext) { y = execute(np); /* subscript */ s = getsval(y); strcat(buf, s); /* BUG: unchecked! */ if (np->nnext) strcat(buf, *SUBSEP); tempfree(y); } if (!isarr(x)) { dprintf( ("making %s into an array\n", x->nval) ); if (freeable(x)) xfree(x->sval); x->tval &= ~(STR|NUM|DONTFREE); x->tval |= ARR; x->sval = (char *) makesymtab(NSYMTAB); } z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval); z->ctype = OCELL; z->csub = CVAR; tempfree(x); return(z); }
void recbld(void) /* create $0 from $1..$NF if necessary */ { int i; char *r, *p; if (donerec == 1) return; r = record; for (i = 1; i <= *NF; i++) { p = getsval(fldtab[i]); if (!adjbuf(&record, &recsize, 1+strlen(p)+r-record, recsize, &r, "recbld 1")) FATAL("created $0 `%.30s...' too long", record); while ((*r = *p++) != 0) r++; if (i < *NF) { if (!adjbuf(&record, &recsize, 2+strlen(*OFS)+r-record, recsize, &r, "recbld 2")) FATAL("created $0 `%.30s...' too long", record); for (p = *OFS; (*r = *p++) != 0; ) r++; } } if (!adjbuf(&record, &recsize, 2+r-record, recsize, &r, "recbld 3")) FATAL("built giant record `%.30s...'", record); *r = '\0'; dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) ); if (freeable(fldtab[0])) xfree(fldtab[0]->sval); fldtab[0]->tval = REC | STR | DONTFREE; fldtab[0]->sval = record; dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) ); dprintf( ("recbld = |%s|\n", record) ); donerec = 1; }
void recbld(void) { int i; register char *r, *p; if (donefld == 0 || donerec == 1) return; r = record; for (i = 1; i <= *NF; i++) { p = getsval(fldtab[i]); while (*r++ = *p++) { if (r >= record+RECSIZE) { size_t diff = r - record; growrec(); r = &record[diff]; } } *(r-1) = **OFS; } *(r-1) = '\0'; dprintf("in recbld FS=%lo, recloc=%lo\n", (long)**FS, (long)recloc); recloc->tval = STR | FLD; dprintf("in recbld FS=%lo, recloc=%lo\n", (long)**FS, (long)recloc); /*if (r > record+RECSIZE) error(FATAL, "built giant record `%.20s...'", record);*/ dprintf("recbld = |%s|\n", record); }
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[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 *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */ { Cell *x, *ap, *k; Node *p; char buf[RECSIZE]; char *s; ap = execute(a[1]); /* array name */ if (!isarr(ap)) { dprintf( ("making %s into an array\n", ap->nval) ); if (freeable(ap)) xfree(ap->sval); ap->tval &= ~(STR|NUM|DONTFREE); ap->tval |= ARR; ap->sval = (char *) makesymtab(NSYMTAB); } buf[0] = 0; for (p = a[0]; p; p = p->nnext) { x = execute(p); /* expr */ s = getsval(x); strcat(buf, s); tempfree(x); if (p->nnext) strcat(buf, *SUBSEP); } k = lookup(buf, (Array *) ap->sval); tempfree(ap); if (k == NULL) return(false); else return(true); }
void recbld(void) /* create $0 from $1..$NF if necessary */ { register int i; register uchar *r, *p; static uchar *rec = 0; if (donerec == 1) return; if (rec == 0) { rec = (uchar *) malloc(recsize); if (rec == 0) ERROR "out of space building $0, record size %d", recsize FATAL; } r = rec; for (i = 1; i <= *NF; i++) { p = getsval(&fldtab[i]); while (r < rec+recsize-1 && (*r = *p++)) r++; if (i < *NF) for (p = *OFS; r < rec+recsize-1 && (*r = *p++); ) r++; } if (r > rec + recsize - 1) ERROR "built giant record `%.30s...'; try -mr n", record FATAL; *r = '\0'; dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) ); recloc->tval = REC | STR | DONTFREE; recloc->sval = record = rec; dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) ); dprintf( ("recbld = |%s|\n", record) ); donerec = 1; }
Cell *adelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ { Cell *x, *y; Node *np; char buf[RECSIZE], *s; x = execute(a[0]); /* Cell* for symbol table */ if (!isarr(x)) return true; if (a[1] == 0) { /* delete the elements, not the table */ freesymtab(x); x->tval &= ~STR; x->tval |= ARR; x->sval = (char *) makesymtab(NSYMTAB); } else { buf[0] = 0; for (np = a[1]; np; np = np->nnext) { y = execute(np); /* subscript */ s = getsval(y); strcat(buf, s); if (np->nnext) strcat(buf, *SUBSEP); tempfree(y); } freeelem(x, buf); } tempfree(x); return true; }
void recbld(void) { int i; unsigned char *r, *p; if (donerec == 1) return; r = recdata; for (i = 1; i <= *NF; i++) { p = getsval(fldtab[i]); while ((*r = *p++)) { if (++r >= &recdata[recsize]) { recsize += CHUNK; growrec(&recdata, &recsize, recsize, &r, 1); } } if (i < *NF) for ((p = *OFS); (*r = *p++); ) { if (++r >= &recdata[recsize]) { recsize += CHUNK; growrec(&recdata, &recsize, recsize, &r, 1); } } } *r = '\0'; dprintf( ("in recbld FS=%o, recloc=%lo\n", **FS, (long)recloc) ); recloc->tval = REC | STR | DONTFREE; recloc->sval = record = recdata; dprintf( ("in recbld FS=%o, recloc=%lo\n", **FS, (long)recloc) ); dprintf( ("recbld = |%s|\n", record) ); donerec = 1; }
Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */ { Cell *y; switch (n) { case EXIT: if (a[0] != NULL) { y = execute(a[0]); errorflag = getfval(y); tempfree(y); } longjmp(env, 1); case RETURN: if (a[0] != NULL) { y = execute(a[0]); if ((y->tval & (STR|NUM)) == (STR|NUM)) { setsval(fp->retval, getsval(y)); fp->retval->fval = getfval(y); fp->retval->tval |= NUM; } else if (y->tval & STR) setsval(fp->retval, getsval(y)); else if (y->tval & NUM) setfval(fp->retval, getfval(y)); else /* can't happen */ ERROR "bad type variable %d", y->tval FATAL; tempfree(y); } return(jret); case NEXT: return(jnext); case NEXTFILE: nextfile(); return(jnextfile); case BREAK: return(jbreak); case CONTINUE: return(jcont); default: /* can't happen */ ERROR "illegal jump type %d", n FATAL; } return 0; /* not reached */ }
char *getargv(int n) /* get ARGV[n] */ { Cell *x; char *s, temp[50]; extern Array *ARGVtab; sprintf(temp, "%d", n); x = setsymtab(temp, "", 0.0, STR, ARGVtab); s = getsval(x); dprintf( ("getargv(%d) returns |%s|\n", n, s) ); return s; }
unsigned char *getargv(int n) /* get ARGV[n] */ { Cell *x; unsigned char *s, temp[25]; extern Array *ARGVtab; snprintf((char *)temp, sizeof temp, "%d", n); x = setsymtab(temp, "", 0.0, STR, ARGVtab); s = getsval(x); dprintf( ("getargv(%d) returns |%s|\n", n, s) ); return s; }
Cell *awkgetline(Node **a, int n) /* get next line from specific input */ { /* a[0] is variable, a[1] is operator, a[2] is filename */ Cell *r, *x; extern Cell **fldtab; FILE *fp; char *buf; int bufsize = recsize; int mode; if ((buf = (char *) malloc(bufsize)) == NULL) FATAL("out of memory in getline"); fflush(stdout); /* in case someone is waiting for a prompt */ r = gettemp(); if (a[1] != NULL) { /* getline < file */ x = execute(a[2]); /* filename */ mode = ptoi(a[1]); if (mode == '|') /* input pipe */ mode = LE; /* arbitrary flag */ fp = openfile(mode, getsval(x)); tempfree(x); if (fp == NULL) n = -1; else n = readrec(&buf, &bufsize, fp); if (n <= 0) { ; } else if (a[0] != NULL) { /* getline var <file */ x = execute(a[0]); setsval(x, buf); tempfree(x); } else { /* getline <file */ setsval(fldtab[0], buf); if (is_number(fldtab[0]->sval)) { fldtab[0]->fval = atof(fldtab[0]->sval); fldtab[0]->tval |= NUM; } } } else { /* bare getline; use current input */ if (a[0] == NULL) /* getline */ n = getrec(&record, &recsize, 1); else { /* getline var */ n = getrec(&buf, &bufsize, 0); x = execute(a[0]); setsval(x, buf); tempfree(x); } } setfval(r, (Awkfloat) n); free(buf); return r; }
Cell *matchop(Node **a, int n) /* ~ and match() */ { Cell *x, *y; char *s, *t; int i; fa *pfa; int (*mf)(fa *, char *) = match, mode = 0; if (n == MATCHFCN) { mf = pmatch; mode = 1; } x = execute(a[1]); /* a[1] = target text */ s = getsval(x); if (a[0] == 0) /* a[1] == 0: already-compiled reg expr */ i = (*mf)((fa *) a[2], s); else { y = execute(a[2]); /* a[2] = regular expr */ t = getsval(y); pfa = makedfa(t, mode); i = (*mf)(pfa, s); tempfree(y); } tempfree(x); if (n == MATCHFCN) { int start = patbeg - s + 1; if (patlen < 0) start = 0; setfval(rstartloc, (Awkfloat) start); setfval(rlengthloc, (Awkfloat) patlen); x = gettemp(); x->tval = NUM; x->fval = start; return x; } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0)) return(true); else return(false); }
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; }
char *getargv(int n) /* get ARGV[n] */ { Cell *x; char *s, temp[50]; extern Array *ARGVtab; snprintf(temp, sizeof(temp), "%d", n); if (lookup(temp, ARGVtab) == NULL) return NULL; x = setsymtab(temp, "", 0.0, STR, ARGVtab); s = getsval(x); dprintf( ("getargv(%d) returns |%s|\n", n, s) ); return s; }
Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */ { Cell *x; Node *y; char 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 *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */ { int k, m, n; char *s; 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 = 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(); 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 *getline(Node **a, int n) /* get next line from specific input */ { /* a[0] is variable, a[1] is operator, a[2] is filename */ Cell *r, *x; char buf[RECSIZE]; FILE *fp; fflush(stdout); /* in case someone is waiting for a prompt */ r = gettemp(); if (a[1] != NULL) { /* getline < file */ x = execute(a[2]); /* filename */ if ((int) a[1] == '|') /* input pipe */ a[1] = (Node *) LE; /* arbitrary flag */ fp = openfile((int) a[1], getsval(x)); tempfree(x); if (fp == NULL) n = -1; else n = readrec(buf, sizeof(buf), fp); if (n <= 0) { ; } else if (a[0] != NULL) { /* getline var <file */ setsval(execute(a[0]), buf); } else { /* getline <file */ if (!(recloc->tval & DONTFREE)) xfree(recloc->sval); strcpy(record, buf); recloc->sval = record; recloc->tval = REC | STR | DONTFREE; if (isnumber(recloc->sval)) { recloc->fval = atof(recloc->sval); recloc->tval |= NUM; } donerec = 1; donefld = 0; } } else { /* bare getline; use current input */ if (a[0] == NULL) /* getline */ n = getrec(record); else { /* getline var */ n = getrec(buf); setsval(execute(a[0]), buf); } } setfval(r, (Awkfloat) n); return r; }
Cell *indirect(Node **a, int n) /* $( a[0] ) */ { Cell *x; int m; char *s; x = execute(a[0]); m = getfval(x); if (m == 0 && !isnumber(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 *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); }