📄 builtin.c
字号:
free_temp(arg); chksize(fw + prec + 9); /* 9==slop */ cp = cpbuf; *cp++ = '%'; if (lj) *cp++ = '-'; if (fill != sp) *cp++ = '0'; if (cur != &fw) { (void) strcpy(cp, "*.*e"); (void) sprintf(obuf + olen, cpbuf, (int) fw, (int) prec, (double) tmpval); } else { (void) strcpy(cp, "*e"); (void) sprintf(obuf + olen, cpbuf, (int) fw, (double) tmpval); } len = strlen(obuf + olen); ofre -= len; olen += len; s0 = s1; break; default: lose: break; } if (toofew) fatal("%s\n\t%s\n\t%*s%s", "not enough arguments to satisfy format string", sfmt->stptr, s1 - sfmt->stptr - 2, "", "^ ran out for this one" ); } if (do_lint && carg != NULL) warning("too many arguments supplied for format string"); bchunk(s0, s1 - s0); free_temp(sfmt); r = make_str_node(obuf, olen, ALREADY_MALLOCED); r->flags |= TEMP; return r;}voiddo_printf(tree)register NODE *tree;{ struct redirect *rp = NULL; register FILE *fp; if (tree->rnode) { int errflg; /* not used, sigh */ rp = redirect(tree->rnode, &errflg); if (rp) { fp = rp->fp; if (!fp) return; } else return; } else fp = stdout; tree = do_sprintf(tree->lnode); efwrite(tree->stptr, sizeof(char), tree->stlen, fp, "printf", rp , 1); free_temp(tree);}NODE *do_sqrt(tree)NODE *tree;{ NODE *tmp; double arg; extern double sqrt P((double)); tmp = tree_eval(tree->lnode); arg = (double) force_number(tmp); free_temp(tmp); if (arg < 0.0) warning("sqrt called with negative argument %g", arg); return tmp_number((AWKNUM) sqrt(arg));}NODE *do_substr(tree)NODE *tree;{ NODE *t1, *t2, *t3; NODE *r; register int indx; size_t length; t1 = tree_eval(tree->lnode); t2 = tree_eval(tree->rnode->lnode); if (tree->rnode->rnode == NULL) /* third arg. missing */ length = t1->stlen; else { t3 = tree_eval(tree->rnode->rnode->lnode); length = (size_t) force_number(t3); free_temp(t3); } indx = (int) force_number(t2) - 1; free_temp(t2); t1 = force_string(t1); if (indx < 0) indx = 0; if (indx >= t1->stlen || length <= 0) { free_temp(t1); return Nnull_string; } if (indx + length > t1->stlen || LONG_MAX - indx < length) length = t1->stlen - indx; r = tmp_string(t1->stptr + indx, length); free_temp(t1); return r;}NODE *do_strftime(tree)NODE *tree;{ NODE *t1, *t2; struct tm *tm; time_t fclock; char buf[100]; int ret; t1 = force_string(tree_eval(tree->lnode)); if (tree->rnode == NULL) /* second arg. missing, default */ (void) time(&fclock); else { t2 = tree_eval(tree->rnode->lnode); fclock = (time_t) force_number(t2); free_temp(t2); } tm = localtime(&fclock); ret = strftime(buf, 100, t1->stptr, tm); return tmp_string(buf, ret);}NODE *do_systime(tree)NODE *tree;{ time_t lclock; (void) time(&lclock); return tmp_number((AWKNUM) lclock);}NODE *do_system(tree)NODE *tree;{ NODE *tmp; int ret = 0; char *cmd; (void) flush_io (); /* so output is synchronous with gawk's */ tmp = tree_eval(tree->lnode); cmd = force_string(tmp)->stptr; if (cmd && *cmd) { ret = system(cmd); ret = (ret >> 8) & 0xff; } free_temp(tmp); return tmp_number((AWKNUM) ret);}void do_print(tree)register NODE *tree;{ register NODE *t1; struct redirect *rp = NULL; register FILE *fp; register char *s; if (tree->rnode) { int errflg; /* not used, sigh */ rp = redirect(tree->rnode, &errflg); if (rp) { fp = rp->fp; if (!fp) return; } else return; } else fp = stdout; tree = tree->lnode; while (tree) { t1 = tree_eval(tree->lnode); if (t1->flags & NUMBER) { if (OFMTidx == CONVFMTidx) (void) force_string(t1); else { char buf[100]; sprintf(buf, OFMT, t1->numbr); t1 = tmp_string(buf, strlen(buf)); } } efwrite(t1->stptr, sizeof(char), t1->stlen, fp, "print", rp, 0); free_temp(t1); tree = tree->rnode; if (tree) { s = OFS; if (OFSlen) efwrite(s, sizeof(char), OFSlen, fp, "print", rp, 0); } } s = ORS; if (ORSlen) efwrite(s, sizeof(char), ORSlen, fp, "print", rp, 1);}NODE *do_tolower(tree)NODE *tree;{ NODE *t1, *t2; register char *cp, *cp2; t1 = tree_eval(tree->lnode); t1 = force_string(t1); t2 = tmp_string(t1->stptr, t1->stlen); for (cp = t2->stptr, cp2 = t2->stptr + t2->stlen; cp < cp2; cp++) if (isupper(*cp)) *cp = tolower(*cp); free_temp(t1); return t2;}NODE *do_toupper(tree)NODE *tree;{ NODE *t1, *t2; register char *cp; t1 = tree_eval(tree->lnode); t1 = force_string(t1); t2 = tmp_string(t1->stptr, t1->stlen); for (cp = t2->stptr; cp < t2->stptr + t2->stlen; cp++) if (islower(*cp)) *cp = toupper(*cp); free_temp(t1); return t2;}NODE *do_atan2(tree)NODE *tree;{ NODE *t1, *t2; extern double atan2 P((double, double)); double d1, d2; t1 = tree_eval(tree->lnode); t2 = tree_eval(tree->rnode->lnode); d1 = force_number(t1); d2 = force_number(t2); free_temp(t1); free_temp(t2); return tmp_number((AWKNUM) atan2(d1, d2));}NODE *do_sin(tree)NODE *tree;{ NODE *tmp; extern double sin P((double)); double d; tmp = tree_eval(tree->lnode); d = sin((double)force_number(tmp)); free_temp(tmp); return tmp_number((AWKNUM) d);}NODE *do_cos(tree)NODE *tree;{ NODE *tmp; extern double cos P((double)); double d; tmp = tree_eval(tree->lnode); d = cos((double)force_number(tmp)); free_temp(tmp); return tmp_number((AWKNUM) d);}static int firstrand = 1;static char state[256];/* ARGSUSED */NODE *do_rand(tree)NODE *tree;{ if (firstrand) { (void) initstate((unsigned) 1, state, sizeof state); srandom(1); firstrand = 0; } return tmp_number((AWKNUM) random() / LONG_MAX);}NODE *do_srand(tree)NODE *tree;{ NODE *tmp; static long save_seed = 0; long ret = save_seed; /* SVR4 awk srand returns previous seed */ if (firstrand) (void) initstate((unsigned) 1, state, sizeof state); else (void) setstate(state); if (!tree) srandom((int) (save_seed = (long) time((time_t *) 0))); else { tmp = tree_eval(tree->lnode); srandom((int) (save_seed = (long) force_number(tmp))); free_temp(tmp); } firstrand = 0; return tmp_number((AWKNUM) ret);}NODE *do_match(tree)NODE *tree;{ NODE *t1; int rstart; AWKNUM rlength; Regexp *rp; t1 = force_string(tree_eval(tree->lnode)); tree = tree->rnode->lnode; rp = re_update(tree); rstart = research(rp, t1->stptr, 0, t1->stlen, 1); if (rstart >= 0) { /* match succeded */ rstart++; /* 1-based indexing */ rlength = REEND(rp, t1->stptr) - RESTART(rp, t1->stptr); } else { /* match failed */ rstart = 0; rlength = -1.0; } free_temp(t1); unref(RSTART_node->var_value); RSTART_node->var_value = make_number((AWKNUM) rstart); unref(RLENGTH_node->var_value); RLENGTH_node->var_value = make_number(rlength); return tmp_number((AWKNUM) rstart);}static NODE *sub_common(tree, global)NODE *tree;int global;{ register char *scan; register char *bp, *cp; char *buf; int buflen; register char *matchend; register int len; char *matchstart; char *text; int textlen; char *repl; char *replend; int repllen; int sofar; int ampersands; int matches = 0; Regexp *rp; NODE *s; /* subst. pattern */ NODE *t; /* string to make sub. in; $0 if none given */ NODE *tmp; NODE **lhs = &tree; /* value not used -- just different from NULL */ int priv = 0; Func_ptr after_assign = NULL; tmp = tree->lnode; rp = re_update(tmp); tree = tree->rnode; s = tree->lnode; tree = tree->rnode; tmp = tree->lnode; t = force_string(tree_eval(tmp)); /* do the search early to avoid work on non-match */ if (research(rp, t->stptr, 0, t->stlen, 1) == -1 || (RESTART(rp, t->stptr) > t->stlen) && (matches = 1)) { free_temp(t); return tmp_number((AWKNUM) matches); } if (tmp->type == Node_val) lhs = NULL; else lhs = get_lhs(tmp, &after_assign); t->flags |= STRING; /* * create a private copy of the string */ if (t->stref > 1 || (t->flags & PERM)) { unsigned int saveflags; saveflags = t->flags; t->flags &= ~MALLOC; tmp = dupnode(t); t->flags = saveflags; t = tmp; priv = 1; } text = t->stptr; textlen = t->stlen; buflen = textlen + 2; s = force_string(tree_eval(s)); repl = s->stptr; replend = repl + s->stlen; repllen = replend - repl; emalloc(buf, char *, buflen, "do_sub"); ampersands = 0; for (scan = repl; scan < replend; scan++) { if (*scan == '&') { repllen--; ampersands++; } else if (*scan == '\\' && (*(scan+1) == '&' || *(scan+1) == '\\')) { repllen--; scan++; } } bp = buf; for (;;) { matches++; matchstart = t->stptr + RESTART(rp, t->stptr); matchend = t->stptr + REEND(rp, t->stptr); /* * create the result, copying in parts of the original * string */ len = matchstart - text + repllen + ampersands * (matchend - matchstart); sofar = bp - buf; while (buflen - sofar - len - 1 < 0) { buflen *= 2; erealloc(buf, char *, buflen, "do_sub"); bp = buf + sofar; } for (scan = text; scan < matchstart; scan++) *bp++ = *scan; for (scan = repl; scan < replend; scan++) if (*scan == '&') for (cp = matchstart; cp < matchend; cp++) *bp++ = *cp; else if (*scan == '\\' && (*(scan+1) == '&' || *(scan+1) == '\\')) { scan++; *bp++ = *scan; } else *bp++ = *scan; if (global && matchstart == matchend && matchend < text + textlen) { *bp++ = *matchend; matchend++; } textlen = text + textlen - matchend; text = matchend; if (!global || textlen <= 0 || research(rp, t->stptr, text-t->stptr, textlen, 1) == -1) break; } sofar = bp - buf; if (buflen - sofar - textlen - 1) { buflen = sofar + textlen + 2; erealloc(buf, char *, buflen, "do_sub"); bp = buf + sofar; } for (scan = matchend; scan < text + textlen; scan++) *bp++ = *scan; textlen = bp - buf; free(t->stptr); t->stptr = buf; t->stlen = textlen; free_temp(s); if (matches > 0 && lhs) { if (priv) { unref(*lhs); *lhs = t; } if (after_assign) (*after_assign)(); t->flags &= ~(NUM|NUMBER); } return tmp_number((AWKNUM) matches);}NODE *do_gsub(tree)NODE *tree;{ return sub_common(tree, 1);}NODE *do_sub(tree)NODE *tree;{ return sub_common(tree, 0);}#ifdef GFMT_WORKAROUND /* * printf's %g format [can't rely on gcvt()] * caveat: don't use as argument to *printf()! */char *gfmt(g, prec, buf)double g; /* value to format */int prec; /* indicates desired significant digits, not decimal places */char *buf; /* return buffer; assumed big enough to hold result */{ if (g == 0.0) { (void) strcpy(buf, "0"); /* easy special case */ } else { register char *d, *e, *p; /* start with 'e' format (it'll provide nice exponent) */ if (prec < 1) prec = 1; /* at least 1 significant digit */ (void) sprintf(buf, "%.*e", prec - 1, g); if ((e = strchr(buf, 'e')) != 0) { /* find exponent */ int exp = atoi(e+1); /* fetch exponent */ if (exp >= -4 && exp < prec) { /* per K&R2, B1.2 */ /* switch to 'f' format and re-do */ prec -= (exp + 1); /* decimal precision */ (void) sprintf(buf, "%.*f", prec, g); e = buf + strlen(buf); } if ((d = strchr(buf, '.')) != 0) { /* remove trailing zeroes and decimal point */ for (p = e; p > d && *--p == '0'; ) continue; if (*p == '.') --p; if (++p < e) /* copy exponent and NUL */ while ((*p++ = *e++) != '\0') continue; } } } return buf;}#endif /* GFMT_WORKAROUND */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -