Путь: Toys/POSIX, команды версии: Ver.4 Ver.9 cut Комментарии в файле cut.c :
Исходный текст в файле cut.c #define FOR_cut #include "toys.h" GLOBALS( char *d, *O; struct arg_list *select[5]; // we treat them the same, so loop through unsigned line; int pairs; regex_t reg; ) // Apply selections to an input line, producing output static void cut_line(char **pline, long len) { unsigned *pairs = (void *)toybuf, wc; char *line; int i, j, k; if (!pline) return; line = *pline; if (len && line[len-1]=='\n') line[--len] = 0; TT.line++; // Loop through selections for (i=0; i<TT.pairs; i++) { unsigned start = pairs[2*i], end = pairs[(2*i)+1], count; char *s = line, *ss, *sss; // when the delimiter is \n output lines. if (*TT.d == '\n') { if (TT.line<start || TT.line>end) { if (i+1 == TT.pairs) return; continue; } goto write_line; } // input: start/end position, count=difference between them // output: s = start of string, len = bytes to output if (start) start--; if (start>=len) continue; if (!end || end>len) end = len; count = end-start; // Find start and end of output string for the relevant selection type if (FLAG(b)) { if (!FLAG(n)) s += start; else { if (end>len) end = len; for (sss = ss = s; (k = (ss-line))<end;) { if (0>(j = utf8towc(&wc, ss, len))) ss++; else { if (((ss += j)-line)<=end) sss = ss; if ((ss-line)<=start) s = ss; } } if (!(count = sss-s)) continue; } } else if (FLAG(C)) { // crunch_str() currently assumes that combining characters get // escaped, to provide an unambiguous visual representation. // This assumes the input string is null terminated. if (start) crunch_str(&s, start, 0, 0, 0); if (!*s) continue; start = s-line; ss = s; crunch_str(&ss, count, 0, 0, 0); count = ss-s; } else if (FLAG(c)) { // Find start ss = line+len; while (start && s<ss) { if (0<=(j = utf8towc(&wc, s, len))) start--; s += (j<1) ? 1 : j; } if (s == ss) continue; // Find end end = count; sss = s; while (end && sss<ss) { if (0<=(j = utf8towc(&wc, sss, len))) end--; sss += (j<1) ? 1 : j; } count = sss-s; } else { regmatch_t match; // Loop through skipping appropriate number of fields for (j = 0; j<2; j++) { ss = s; if (j) start = count; else end = start; while (*ss && start) { if (FLAG(f)) { if (!strchr(TT.d, *ss++)) continue; if (!--start && j) ss--; } else { if (regexec(&TT.reg, ss, 1, &match, REG_NOTBOL|REG_NOTEOL)) { ss = line+len; continue; } if (!match.rm_eo) break; // zero length match == no delimiter ss += (!--start && j) ? match.rm_so : match.rm_eo; } } if (!j && !*(s = ss)) break; } // If we never encountered even one separator, print whole line (posix!) if (!j && end == start) { if (FLAG(D)) break; if (FLAG(s)) return; write_line: fwrite(line, len, 1, stdout); break; } else if (!*s) continue; count = ss-s; } if (i && TT.O) fputs(TT.O, stdout); fwrite(s, count, 1, stdout); } xputc('\n'); } static int compar(unsigned *a, unsigned *b) { if (*a<*b) return -1; if (*a>*b) return 1; if (a[1]<b[1]) return -1; if (a[1]>b[1]) return 1; return 0; } // parse A or A-B or A- or -B static char *get_range(void *data, char *str, int len) { char *end = str; unsigned *pairs = (void *)toybuf, i; // Using toybuf[] to store ranges means we can have 512 selections max. if (TT.pairs == sizeof(toybuf)/sizeof(int)) perror_exit("select limit"); pairs += 2*TT.pairs++; pairs[1] = UINT_MAX; for (i = 0; ;i++) { if (i==2) return end; if (isdigit(*end)) { long long ll = estrtol(end, &end, 10); if (ll<1 || ll>UINT_MAX || errno) return end; pairs[i] = ll; } if (*end++ != '-') break; } if (!i) pairs[1] = pairs[0]; if ((end-str)<len) return end; if (pairs[0]>pairs[1]) return str; // No error return 0; } void cut_main(void) { int i; char buf[8]; // Parse command line arguments if ((toys.optflags&(FLAG_s|FLAG_f|FLAG_F))==FLAG_s) error_exit("-s needs -Ff"); if ((toys.optflags&(FLAG_d|FLAG_f|FLAG_F))==FLAG_d) error_exit("-d needs -Ff"); if (!TT.d) TT.d = (FLAG(F)) ? "[[:space:]][[:space:]]*" : "\t"; if (FLAG(F)) xregcomp(&TT.reg, TT.d, REG_EXTENDED); if (!TT.O) { if (FLAG(F)) TT.O = " "; else if (FLAG(f)) TT.O = TT.d; } // Parse ranges, which are attached to a selection type (only one can be set) for (i = 0; i<ARRAY_LEN(TT.select); i++) { sprintf(buf, "bad -%c", "CFfcb"[i]); // reverse order from newtoy optstr if (TT.select[i]) comma_args(TT.select[i], 0, buf, get_range); } if (!TT.pairs) error_exit("no selections"); // Sort and collate selections if (!FLAG(D)) { int from, to; unsigned *pairs = (void *)toybuf; qsort(toybuf, TT.pairs, 8, (void *)compar); for (to = 0, from = 2; from/2 < TT.pairs; from += 2) { if (pairs[from] > pairs[to+1]) { to += 2; memcpy(pairs+to, pairs+from, 2*sizeof(unsigned)); } else if (pairs[from+1] > pairs[to+1]) pairs[to+1] = pairs[from+1]; } TT.pairs = (to/2)+1; } // For each argument, loop through lines of file and call cut_line() on each loopfiles_lines(toys.optargs, cut_line); } |