double setattr(obj *p, int type, double val) { int cw_switch; double x, y; obj *q; if (p->o_type == BLOCK) { for (q = p->o_next; q != p->o_val[N_VAL].o; q = q->o_next) setattr (q, type, val); } else if (p->o_type <= TEXT) switch (type) { case TCOLOR: if (val >= 0.0 || checkcolor(val) >= 0.0) p->o_text = val; break; case LCOLOR: if (val >= 0.0 || checkcolor(val) >= 0.0) p->o_color = val; break; case PCOLOR: if (val < 0.0 || checkcolor(val) < 0.0) p->o_attr &= ~FILLED; else { p->o_fill = val; /* ignored for TEXT? */ p->o_attr |= FILLED; } break; case LAYER: if (val < -128) val = -128; else if (val > 127) val = 127; p->o_layer = (short)val; if (val > getfval("maxlayer")) setfval ("maxlayer", val); break; case LWEIGHT: p->o_weight = val; break; case NOEDGE: if (val != 0.0) p->o_attr &= ~EDGED; else p->o_attr |= EDGED; break; case CCW: case CW: if (p->o_type == ARC) { cw_switch = (p->o_attr & CW_ARC); if (type == CW) cw_switch = !cw_switch; if (cw_switch) { x = p->o_val[N_VAL+2].f; y = p->o_val[N_VAL+3].f; p->o_val[N_VAL+2] = p->o_val[N_VAL+4]; p->o_val[N_VAL+3] = p->o_val[N_VAL+5]; /* exchange from & to */ p->o_val[N_VAL+4].f = x; p->o_val[N_VAL+5].f = y; p->o_attr ^= (p->o_attr & CW_ARC); } } break; case DIAMETER: val /= 2; case RADIUS: switch (p->o_type) { case ARROW: case LINE: case BOX: case ARC: case SECTOR: p->o_val[N_VAL].f = val; break; case CIRCLE: case ELLIPSE: p->o_wid = val * 2; break; } break; case WIDTH: p->o_wid = val; break; case HEIGHT: p->o_ht = val; break; default: yyerror ("can't happen setattr"); } return val; }
void fldbld(void) { register char *r, *fr; wchar_t wc, sep; int i, j, n; r = record; fr = fields; i = 0; /* number of fields accumulated here */ next(sep, *FS, n); if (sep == ' ') for (i = 0; ; ) { while (*r == ' ' || *r == '\t' || *r == '\n') r++; if (*r == 0) break; i++; if (i >= MAXFLD) morefields(); if (!(fldtab[i]->tval&FLD)) strfree(fldtab[i]->sval); fldtab[i]->sval = fr; fldtab[i]->tval = FLD | STR; next(wc, r, n); do { do *fr++ = *r++; while (--n); next(wc, r, n); } while (wc != ' ' && wc != '\t' && wc != '\n' && wc != '\0'); *fr++ = 0; } else if (*r != 0) /* if 0, it's a null field */ for (;;) { i++; if (i >= MAXFLD) morefields(); if (!(fldtab[i]->tval&FLD)) strfree(fldtab[i]->sval); fldtab[i]->sval = fr; fldtab[i]->tval = FLD | STR; while (next(wc, r, n), wc != sep && wc != '\n' && wc != '\0') { /* \n always a separator */ do *fr++ = *r++; while (--n); } *fr++ = '\0'; if (wc == '\0') break; r += n; } *fr = 0; for (j=MAXFLD-1; j>i; j--) { /* clean out junk from previous record */ if (!(fldtab[j]->tval&FLD)) strfree(fldtab[j]->sval); fldtab[j]->tval = STR | FLD; fldtab[j]->sval = EMPTY; } maxfld = i; donefld = 1; for(i=1; i<=maxfld; i++) if(isanumber(fldtab[i]->sval)) { fldtab[i]->fval = atof(fldtab[i]->sval); fldtab[i]->tval |= NUM; } setfval(lookup("NF", symtab, 0), (awkfloat) maxfld); if (dbg) for (i = 0; i <= maxfld; i++) printf("field %d: |%s|\n", i, fldtab[i]->sval); }
void fldbld(void) /* create fields from current record */ { register uchar *r, *fr, sep; Cell *p; int i; if (donefld) return; if (!(recloc->tval & STR)) getsval(recloc); r = recloc->sval; fr = fields; i = 0; /* number of fields accumulated here */ if (strlen(*FS) > 1) { /* it's a regular expression */ i = refldbld(r, *FS); } else if ((sep = **FS) == ' ') { /* default whitespace */ for (i = 0; ; ) { while (*r == ' ' || *r == '\t' || *r == '\n') r++; if (*r == 0) break; i++; if (i >= nfields) break; if (!(fldtab[i].tval & DONTFREE)) xfree(fldtab[i].sval); fldtab[i].sval = fr; fldtab[i].tval = FLD | STR | DONTFREE; do *fr++ = *r++; while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0'); *fr++ = 0; } *fr = 0; } else if (*r != 0) { /* if 0, it's a null field */ for (;;) { i++; if (i >= nfields) break; if (!(fldtab[i].tval & DONTFREE)) xfree(fldtab[i].sval); fldtab[i].sval = fr; fldtab[i].tval = FLD | STR | DONTFREE; while (*r != sep && *r != '\n' && *r != '\0') /* \n is always a separator */ *fr++ = *r++; *fr++ = 0; if (*r++ == 0) break; } *fr = 0; } if (i >= nfields) ERROR "record `%.30s...' has too many fields; try -mf n", record FATAL; /* clean out junk from previous record */ cleanfld(i, maxfld); maxfld = i; donefld = 1; for (p = fldtab+1; p <= fldtab+maxfld; p++) { if(isnumber(p->sval)) { p->fval = atof(p->sval); p->tval |= NUM; } } setfval(nfloc, (Awkfloat) maxfld); if (dbg) for (p = fldtab; p <= fldtab+maxfld; p++) printf("field %d: |%s|\n", p-fldtab, p->sval); }
int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */ { /* note: cares whether buf == record */ int c; char *buf = *pbuf; uschar saveb0; int bufsize = *pbufsize, savebufsize = bufsize; if (firsttime) { firsttime = 0; initgetrec(); } dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n", *RS, *FS, *ARGC, *FILENAME) ); if (isrecord) { donefld = 0; donerec = 1; } saveb0 = buf[0]; buf[0] = 0; while (argno < *ARGC || infile == stdin) { dprintf( ("argno=%d, file=|%s|\n", argno, file) ); if (infile == NULL) { /* have to open a new file */ file = getargv(argno); if (file == NULL || *file == '\0') { /* deleted or zapped */ argno++; continue; } if (isclvar(file)) { /* a var=value arg */ setclvar(file); argno++; continue; } *FILENAME = file; dprintf( ("opening file %s\n", file) ); if (*file == '-' && *(file+1) == '\0') infile = stdin; else if ((infile = fopen(file, "r")) == NULL) FATAL("can't open file %s", file); setfval(fnrloc, 0.0); } c = readrec(&buf, &bufsize, infile); if (c != 0 || buf[0] != '\0') { /* normal record */ if (isrecord) { if (freeable(fldtab[0])) xfree(fldtab[0]->sval); fldtab[0]->sval = buf; /* buf == record */ fldtab[0]->tval = REC | STR | DONTFREE; if (is_number(fldtab[0]->sval)) { fldtab[0]->fval = atof(fldtab[0]->sval); fldtab[0]->tval |= NUM; } } setfval(nrloc, nrloc->fval+1); setfval(fnrloc, fnrloc->fval+1); *pbuf = buf; *pbufsize = bufsize; return 1; } /* EOF arrived on this file; set up next */ if (infile != stdin) fclose(infile); infile = NULL; argno++; } buf[0] = saveb0; *pbuf = buf; *pbufsize = savebufsize; return 0; /* true end of file */ }
void fldbld(void) /* create fields from current record */ { /* this relies on having fields[] the same length as $0 */ /* the fields are all stored in this one array with \0's */ /* possibly with a final trailing \0 not associated with any field */ char *r, *fr, sep; Cell *p; int i, j, n; if (donefld) return; if (!isstr(fldtab[0])) getsval(fldtab[0]); r = fldtab[0]->sval; n = strlen(r); if (n > fieldssize) { xfree(fields); if ((fields = (char *) malloc(n+2)) == NULL) /* possibly 2 final \0s */ FATAL("out of space for fields in fldbld %d", n); fieldssize = n; } fr = fields; i = 0; /* number of fields accumulated here */ strlcpy(inputFS, *FS, sizeof(inputFS)); if (strlen(inputFS) > 1) { /* it's a regular expression */ i = refldbld(r, inputFS); } else if ((sep = *inputFS) == ' ') { /* default whitespace */ for (i = 0; ; ) { while (*r == ' ' || *r == '\t' || *r == '\n') r++; if (*r == 0) break; i++; if (i > nfields) growfldtab(i); if (freeable(fldtab[i])) xfree(fldtab[i]->sval); fldtab[i]->sval = fr; fldtab[i]->tval = FLD | STR | DONTFREE; do *fr++ = *r++; while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0'); *fr++ = 0; } *fr = 0; } else if ((sep = *inputFS) == 0) { /* new: FS="" => 1 char/field */ for (i = 0; *r != 0; r++) { char buf[2]; i++; if (i > nfields) growfldtab(i); if (freeable(fldtab[i])) xfree(fldtab[i]->sval); buf[0] = *r; buf[1] = 0; fldtab[i]->sval = tostring(buf); fldtab[i]->tval = FLD | STR; } *fr = 0; } else if (*r != 0) { /* if 0, it's a null field */ /* subtlecase : if length(FS) == 1 && length(RS > 0) * \n is NOT a field separator (cf awk book 61,84). * this variable is tested in the inner while loop. */ int rtest = '\n'; /* normal case */ if (strlen(*RS) > 0) rtest = '\0'; for (;;) { i++; if (i > nfields) growfldtab(i); if (freeable(fldtab[i])) xfree(fldtab[i]->sval); fldtab[i]->sval = fr; fldtab[i]->tval = FLD | STR | DONTFREE; while (*r != sep && *r != rtest && *r != '\0') /* \n is always a separator */ *fr++ = *r++; *fr++ = 0; if (*r++ == 0) break; } *fr = 0; } if (i > nfields) FATAL("record `%.30s...' has too many fields; can't happen", r); cleanfld(i+1, lastfld); /* clean out junk from previous record */ lastfld = i; donefld = 1; for (j = 1; j <= lastfld; j++) { p = fldtab[j]; if(is_number(p->sval)) { p->fval = atof(p->sval); p->tval |= NUM; } } setfval(nfloc, (Awkfloat) lastfld); if (dbg) { for (j = 0; j <= lastfld; j++) { p = fldtab[j]; printf("field %d (%s): |%s|\n", j, p->nval, p->sval); } } }
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 (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 *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */ { Cell *x, *y; Awkfloat u; int t; Awkfloat tmp; char *p, *buf; Node *nextarg; FILE *fp; void flush_all(void); t = ptoi(a[0]); x = execute(a[1]); nextarg = a[1]->nnext; switch (t) { case FLENGTH: if (isarr(x)) u = ((Array *) x->sval)->nelem; /* GROT. should be function*/ else 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) { 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); tmp = u; srand((unsigned int) u); u = srand_seed; srand_seed = tmp; break; case FTOUPPER: case FTOLOWER: buf = tostring(getsval(x)); if (t == FTOUPPER) { for (p = buf; *p; p++) if (islower((uschar) *p)) *p = toupper((uschar)*p); } else { for (p = buf; *p; p++) if (isupper((uschar) *p)) *p = tolower((uschar)*p); } tempfree(x); x = gettemp(); setsval(x, buf); free(buf); return x; case FFLUSH: if (isrec(x) || strlen(getsval(x)) == 0) { flush_all(); /* fflush() or fflush("") -> all */ u = 0; } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL) u = EOF; else u = fflush(fp); break; 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 *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); }
void fldbld(void) { register unsigned char *r, *fr; Cell **p; wchar_t wc, sep; int i, n; if (donefld) return; if (!(recloc->tval & STR)) getsval(recloc); r = recloc->sval; /* was record! */ fr = fields; i = 0; /* number of fields accumulated here */ if ((sep = **FS) != '\0' && (next(sep, *FS, n), (*FS)[n] != '\0')) { /* it's a regular expression */ i = refldbld(r, *FS); } else if (sep == ' ') { for (i = 0; ; ) { while (*r == ' ' || *r == '\t' || *r == '\n') r++; if (*r == 0) break; i++; if (i >= MAXFLD) morefields(); if (!(fldtab[i]->tval & DONTFREE)) xfree(fldtab[i]->sval); fldtab[i]->sval = fr; fldtab[i]->tval = FLD | STR | DONTFREE; next(wc, r, n); do { do *fr++ = *r++; while (--n); next(wc, r, n); } while (wc != ' ' && wc != '\t' && wc != '\n' && wc != '\0'); *fr++ = 0; } *fr = 0; } else if (*r != 0) { /* if 0, it's a null field */ for (;;) { i++; if (i >= MAXFLD) morefields(); if (!(fldtab[i]->tval & DONTFREE)) xfree(fldtab[i]->sval); fldtab[i]->sval = fr; fldtab[i]->tval = FLD | STR | DONTFREE; while (next(wc, r, n), wc != sep && wc != '\n' && wc != '\0') { /* \n always a separator */ do *fr++ = *r++; while (--n); } *fr++ = '\0'; if (wc == '\0') break; r += n; } *fr = 0; } /*if (i >= MAXFLD) error(MM_ERROR, ":13:Record `%.20s...' has too many fields", record);*/ /* clean out junk from previous record */ cleanfld(i, maxfld); maxfld = i; donefld = 1; for (p = &fldtab[1]; p <= &fldtab[0]+maxfld; p++) (void)is2number(0, *p); setfval(nfloc, (Awkfloat) maxfld); if (dbg) for (p = &fldtab[0]; p <= &fldtab[0]+maxfld; p++) pfmt(stdout, MM_INFO, ":14:field %d: |%s|\n", p-&fldtab[0], (*p)->sval); }
int getrec(unsigned char **buf, int *bufsize) { int c, saved; static int firsttime = 1; if (firsttime) { firsttime = 0; initgetrec(); } dprintf( ("RS=<%s>, FS=<%s>, ARGC=%d, FILENAME=%s\n", *RS ? *RS : tostring(""), *FS ? *FS : tostring(""), (int) *ARGC, *FILENAME ? *FILENAME : tostring("")) ); donefld = 0; donerec = 1; if (*bufsize == 0) { if ((*buf = malloc(*bufsize = CHUNK)) == NULL) error(MM_ERROR, outofspace, "getrec"); **buf = '\0'; } saved = (*buf)[0]; (*buf)[0] = 0; while (argno < *ARGC || infile == stdin) { dprintf( ("argno=%d, file=|%s|\n", argno, file) ) ; if (infile == NULL) { /* have to open a new file */ file = getargv(argno); if (*file == '\0') { /* it's been zapped */ argno++; continue; } if (isclvar(file)) { /* a var=value arg */ setclvar(file); argno++; continue; } *FILENAME = file; dprintf( ("opening file %s\n", file) ); if (*file == '-' && *(file+1) == '\0') infile = stdin; else if ((infile = fopen((char *)file, "r")) == NULL) error(MM_ERROR, badopen, file, strerror(errno)); setfval(fnrloc, 0.0); } c = readrec(buf, bufsize, infile); if (c != 0 || (*buf)[0] != '\0') { /* normal record */ if (*buf == record) { if (!(recloc->tval & DONTFREE)) xfree(recloc->sval); recloc->sval = record; recloc->tval = REC | STR | DONTFREE; (void)is2number(0, recloc); } setfval(nrloc, nrloc->fval+1); setfval(fnrloc, fnrloc->fval+1); return 1; } /* EOF arrived on this file; set up next */ if (infile != stdin) fclose(infile); infile = NULL; argno++; } /* * POSIX.2 requires that NF stick with its last value * at the start of the END code. The most straightforward * way to do this is to restore the contents of record * [==buf when called from program()] so that getnf() will * recompute the same NF value unless something strange * occurs. This has the side effect of $0...$NF *also* * having sticky values into END, but that seems to match * the spirit of POSIX.2's rule for NF. */ if (posix) (*buf)[0] = saved; return 0; /* true end of file */ }