📄 field.c
字号:
}/* * this is called both from get_field() and from do_split() * via (*parse_field)(). This variation is for when FS is a single character * other than space. */static intsc_parse_field(up_to, buf, len, fs, rp, set, n)int up_to; /* parse only up to this field number */char **buf; /* on input: string to parse; on output: point to start next */int len;NODE *fs;Regexp *rp;void (*set) (); /* routine to set the value of the parsed field */NODE *n;{ register char *scan = *buf; register char fschar; register int nf = parse_high_water; register char *field; register char *end = scan + len; char sav; if (up_to == HUGE) nf = 0; if (len == 0) return nf; if (*RS == 0 && fs->stlen == 0) fschar = '\n'; else fschar = fs->stptr[0]; /* before doing anything save the char at *end */ sav = *end; /* because it will be destroyed now: */ *end = fschar; /* sentinel character */ for (; nf < up_to; scan++) { field = scan; while (*scan++ != fschar) ; scan--; (*set)(++nf, field, (int)(scan - field), n); if (scan == end) break; } /* everything done, restore original char at *end */ *end = sav; *buf = scan; return nf;}/* * this is called both from get_field() and from do_split() * via (*parse_field)(). This variation is for fields are fixed widths. */static intfw_parse_field(up_to, buf, len, fs, rp, set, n)int up_to; /* parse only up to this field number */char **buf; /* on input: string to parse; on output: point to start next */int len;NODE *fs;Regexp *rp;void (*set) (); /* routine to set the value of the parsed field */NODE *n;{ register char *scan = *buf; register int nf = parse_high_water; register char *end = scan + len; if (up_to == HUGE) nf = 0; if (len == 0) return nf; for (; nf < up_to && (len = FIELDWIDTHS[nf+1]) != -1; ) { if (len > end - scan) len = end - scan; (*set)(++nf, scan, len, n); scan += len; } if (len == -1) *buf = end; else *buf = scan; return nf;}NODE **get_field(requested, assign)register int requested;Func_ptr *assign; /* this field is on the LHS of an assign */{ /* * if requesting whole line but some other field has been altered, * then the whole line must be rebuilt */ if (requested == 0) { if (!field0_valid) { /* first, parse remainder of input record */ if (NF == -1) { NF = (*parse_field)(HUGE-1, &parse_extent, fields_arr[0]->stlen - (parse_extent - fields_arr[0]->stptr), save_FS, FS_regexp, set_field, (NODE *)NULL); parse_high_water = NF; } rebuild_record(); } if (assign) *assign = reset_record; return &fields_arr[0]; } /* assert(requested > 0); */ if (assign) field0_valid = 0; /* $0 needs reconstruction */ if (requested <= parse_high_water) /* already parsed this field */ return &fields_arr[requested]; if (NF == -1) { /* have not yet parsed to end of record */ /* * parse up to requested fields, calling set_field() for each, * saving in parse_extent the point where the parse left off */ if (parse_high_water == 0) /* starting at the beginning */ parse_extent = fields_arr[0]->stptr; parse_high_water = (*parse_field)(requested, &parse_extent, fields_arr[0]->stlen - (parse_extent-fields_arr[0]->stptr), save_FS, FS_regexp, set_field, (NODE *)NULL); /* * if we reached the end of the record, set NF to the number of * fields so far. Note that requested might actually refer to * a field that is beyond the end of the record, but we won't * set NF to that value at this point, since this is only a * reference to the field and NF only gets set if the field * is assigned to -- this case is handled below */ if (parse_extent == fields_arr[0]->stptr + fields_arr[0]->stlen) NF = parse_high_water; if (requested == HUGE-1) /* HUGE-1 means set NF */ requested = parse_high_water; } if (parse_high_water < requested) { /* requested beyond end of record */ if (assign) { /* expand record */ register int i; if (requested > nf_high_water) grow_fields_arr(requested); /* fill in fields that don't exist */ for (i = parse_high_water + 1; i <= requested; i++) fields_arr[i] = Nnull_string; NF = requested; parse_high_water = requested; } else return &Nnull_string; } return &fields_arr[requested];}static voidset_element(num, s, len, n)int num;char *s;int len;NODE *n;{ register NODE *it; it = make_string(s, len); it->flags |= MAYBE_NUM; *assoc_lookup(n, tmp_number((AWKNUM) (num))) = it;}NODE *do_split(tree)NODE *tree;{ NODE *t1, *t2, *t3, *tmp; NODE *fs; char *s; int (*parseit)P((int, char **, int, NODE *, Regexp *, void (*)(), NODE *)); Regexp *rp = NULL; t1 = tree_eval(tree->lnode); t2 = tree->rnode->lnode; t3 = tree->rnode->rnode->lnode; (void) force_string(t1); if (t2->type == Node_param_list) t2 = stack_ptr[t2->param_cnt]; if (t2->type != Node_var && t2->type != Node_var_array) fatal("second argument of split is not a variable"); assoc_clear(t2); if (t3->re_flags & FS_DFLT) { parseit = parse_field; fs = force_string(FS_node->var_value); rp = FS_regexp; } else { tmp = force_string(tree_eval(t3->re_exp)); if (tmp->stlen == 1) { if (tmp->stptr[0] == ' ') parseit = def_parse_field; else parseit = sc_parse_field; } else { parseit = re_parse_field; rp = re_update(t3); } fs = tmp; } s = t1->stptr; tmp = tmp_number((AWKNUM) (*parseit)(HUGE, &s, (int)t1->stlen, fs, rp, set_element, t2)); free_temp(t1); free_temp(t3); return tmp;}voidset_FS(){ NODE *tmp = NULL; char buf[10]; NODE *fs; buf[0] = '\0'; default_FS = 0; if (FS_regexp) { refree(FS_regexp); FS_regexp = NULL; } fs = force_string(FS_node->var_value); if (fs->stlen > 1) parse_field = re_parse_field; else if (*RS == 0) { parse_field = sc_parse_field; if (fs->stlen == 1) { if (fs->stptr[0] == ' ') { default_FS = 1; strcpy(buf, "[ \t\n]+"); } else if (fs->stptr[0] != '\n') sprintf(buf, "[%c\n]", fs->stptr[0]); } } else { parse_field = def_parse_field; if (fs->stptr[0] == ' ' && fs->stlen == 1) default_FS = 1; else if (fs->stptr[0] != ' ' && fs->stlen == 1) { if (IGNORECASE == 0) parse_field = sc_parse_field; else sprintf(buf, "[%c]", fs->stptr[0]); } } if (buf[0]) { FS_regexp = make_regexp(buf, strlen(buf), IGNORECASE, 1); parse_field = re_parse_field; } else if (parse_field == re_parse_field) { FS_regexp = make_regexp(fs->stptr, fs->stlen, IGNORECASE, 1); } else FS_regexp = NULL; resave_fs = 1;}voidset_RS(){ (void) force_string(RS_node->var_value); RS = RS_node->var_value->stptr; set_FS();}voidset_FIELDWIDTHS(){ register char *scan; char *end; register int i; static int fw_alloc = 1; static int warned = 0; extern double strtod(); if (do_lint && ! warned) { warned = 1; warning("use of FIELDWIDTHS is a gawk extension"); } if (do_unix) /* quick and dirty, does the trick */ return; parse_field = fw_parse_field; scan = force_string(FIELDWIDTHS_node->var_value)->stptr; end = scan + 1; if (FIELDWIDTHS == NULL) emalloc(FIELDWIDTHS, int *, fw_alloc * sizeof(int), "set_FIELDWIDTHS"); FIELDWIDTHS[0] = 0; for (i = 1; ; i++) { if (i >= fw_alloc) { fw_alloc *= 2; erealloc(FIELDWIDTHS, int *, fw_alloc * sizeof(int), "set_FIELDWIDTHS"); } FIELDWIDTHS[i] = (int) strtod(scan, &end); if (end == scan) break; scan = end; } FIELDWIDTHS[i] = -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -