static void sequential(struct fdescr *dsc, int fdescrlen, Rune *delim, size_t delimlen) { Rune c, last; size_t i, d; for (i = 0; i < fdescrlen; i++) { d = 0; last = 0; while (efgetrune(&c, dsc[i].fp, dsc[i].name)) { if (last == '\n') { if (delim[d] != '\0') efputrune(&delim[d], stdout, "<stdout>"); d = (d + 1) % delimlen; } if (c != '\n') efputrune(&c, stdout, "<stdout>"); last = c; } if (last == '\n') efputrune(&last, stdout, "<stdout>"); } }
static void strings(FILE *fp, const char *fname, size_t len) { Rune r, *rbuf; size_t i, bread; off_t off; rbuf = ereallocarray(NULL, len, sizeof(*rbuf)); for (off = 0, i = 0; (bread = efgetrune(&r, fp, fname)); ) { off += bread; if (r == Runeerror) continue; if (!isprintrune(r)) { if (i > len) putchar('\n'); i = 0; continue; } if (i < len) { rbuf[i++] = r; continue; } else if (i > len) { efputrune(&r, stdout, "<stdout>"); continue; } printf(format, (long)off - i); for (i = 0; i < len; i++) efputrune(rbuf + i, stdout, "<stdout>"); efputrune(&r, stdout, "<stdout>"); i++; } free(rbuf); }
static void unexpand(const char *file, FILE *fp) { Rune r; size_t last = 0, col = 0, i; int bol = 1; while (efgetrune(&r, fp, file)) { switch (r) { case ' ': if (!bol && !aflag) last++; col++; break; case '\t': if (tablistlen == 1) { if (!bol && !aflag) last += tablist[0] - col % tablist[0]; col += tablist[0] - col % tablist[0]; } else { for (i = 0; i < tablistlen; i++) if (col < tablist[i]) break; if (!bol && !aflag) last = tablist[i]; col = tablist[i]; } break; case '\b': if (bol || aflag) unexpandspan(last, col); col -= (col > 0); last = col; bol = 0; break; case '\n': if (bol || aflag) unexpandspan(last, col); last = col = 0; bol = 1; break; default: if (bol || aflag) unexpandspan(last, col); last = ++col; bol = 0; break; } if ((r != ' ' && r != '\t') || (!aflag && !bol)) efputrune(&r, stdout, "<stdout>"); } if (last < col && (bol || aflag)) unexpandspan(last, col); }
static void parallel(struct fdescr *dsc, int fdescrlen, Rune *delim, size_t delimlen) { Rune c, d; size_t i, m; ssize_t last; nextline: last = -1; for (i = 0; i < fdescrlen; i++) { d = delim[i % delimlen]; c = 0; for (; efgetrune(&c, dsc[i].fp, dsc[i].name) ;) { for (m = last + 1; m < i; m++) efputrune(&(delim[m % delimlen]), stdout, "<stdout>"); last = i; if (c == '\n') { if (i != fdescrlen - 1) c = d; efputrune(&c, stdout, "<stdout>"); break; } efputrune(&c, stdout, "<stdout>"); } if (c == 0 && last != -1) { if (i == fdescrlen - 1) putchar('\n'); else efputrune(&d, stdout, "<stdout>"); last++; } } if (last != -1) goto nextline; }
static void unexpandspan(size_t last, size_t col) { size_t off, i, j; Rune r; if (tablistlen == 1) { i = 0; off = last % tablist[i]; if ((col - last) + off >= tablist[i] && last < col) last -= off; r = '\t'; for (; last + tablist[i] <= col; last += tablist[i]) efputrune(&r, stdout, "<stdout>"); r = ' '; for (; last < col; last++) efputrune(&r, stdout, "<stdout>"); } else { for (i = 0; i < tablistlen; i++) if (col < tablist[i]) break; for (j = 0; j < tablistlen; j++) if (last < tablist[j]) break; r = '\t'; for (; j < i; j++) { efputrune(&r, stdout, "<stdout>"); last = tablist[j]; } r = ' '; for (; last < col; last++) efputrune(&r, stdout, "<stdout>"); } }
int main(int argc, char *argv[]) { Rune *rarg; size_t i, j, argi, lastargi, formatlen, blen; long long num; double dou; int cooldown = 0, width, precision, ret = 0; char *format, *tmp, *arg, *fmt, flag; argv0 = argv[0]; if (argc < 2) usage(); format = argv[1]; if ((tmp = strstr(format, "\\c"))) { *tmp = 0; cooldown = 1; } formatlen = unescape(format); if (formatlen == 0) return 0; lastargi = 0; for (i = 0, argi = 2; !cooldown || i < formatlen; i++, i = cooldown ? i : (i % formatlen)) { if (i == 0) { if (lastargi == argi) break; lastargi = argi; } if (format[i] != '%') { putchar(format[i]); continue; } /* flag */ for (flag = '\0', i++; strchr("#-+ 0", format[i]); i++) { flag = format[i]; } /* field width */ width = -1; if (format[i] == '*') { if (argi < argc) width = estrtonum(argv[argi++], 0, INT_MAX); else cooldown = 1; i++; } else { j = i; for (; strchr("+-0123456789", format[i]); i++); if (j != i) { tmp = estrndup(format + j, i - j); width = estrtonum(tmp, 0, INT_MAX); free(tmp); } else { width = 0; } } /* field precision */ precision = -1; if (format[i] == '.') { if (format[++i] == '*') { if (argi < argc) precision = estrtonum(argv[argi++], 0, INT_MAX); else cooldown = 1; i++; } else { j = i; for (; strchr("+-0123456789", format[i]); i++); if (j != i) { tmp = estrndup(format + j, i - j); precision = estrtonum(tmp, 0, INT_MAX); free(tmp); } else { precision = 0; } } } if (format[i] != '%') { if (argi < argc) arg = argv[argi++]; else { arg = ""; cooldown = 1; } } else { putchar('%'); continue; } switch (format[i]) { case 'b': if ((tmp = strstr(arg, "\\c"))) { *tmp = 0; blen = unescape(arg); fwrite(arg, sizeof(*arg), blen, stdout); return 0; } blen = unescape(arg); fwrite(arg, sizeof(*arg), blen, stdout); break; case 'c': unescape(arg); rarg = ereallocarray(NULL, utflen(arg) + 1, sizeof(*rarg)); utftorunestr(arg, rarg); efputrune(rarg, stdout, "<stdout>"); free(rarg); break; case 's': printf("%*.*s", width, precision, arg); break; case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': for (j = 0; isspace(arg[j]); j++); if (arg[j] == '\'' || arg[j] == '\"') { arg += j + 1; unescape(arg); rarg = ereallocarray(NULL, utflen(arg) + 1, sizeof(*rarg)); utftorunestr(arg, rarg); num = rarg[0]; } else if (arg[0]) { errno = 0; if (format[i] == 'd' || format[i] == 'i') num = strtol(arg, &tmp, 0); else num = strtoul(arg, &tmp, 0); if (tmp == arg || *tmp != '\0') { ret = 1; weprintf("%%%c %s: conversion error\n", format[i], arg); } if (errno == ERANGE) { ret = 1; weprintf("%%%c %s: out of range\n", format[i], arg); } } else { num = 0; } fmt = estrdup(flag ? "%#*.*ll#" : "%*.*ll#"); if (flag) fmt[1] = flag; fmt[flag ? 7 : 6] = format[i]; printf(fmt, width, precision, num); free(fmt); break; case 'a': case 'A': case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': fmt = estrdup(flag ? "%#*.*#" : "%*.*#"); if (flag) fmt[1] = flag; fmt[flag ? 5 : 4] = format[i]; dou = (strlen(arg) > 0) ? estrtod(arg) : 0; printf(fmt, width, precision, dou); free(fmt); break; default: eprintf("Invalid format specifier '%c'.\n", format[i]); } if (argi >= argc) cooldown = 1; } return fshut(stdout, "<stdout>") | ret; }