diff options
Diffstat (limited to 'usr/src/lib/libcmd/common/cat.c')
-rw-r--r-- | usr/src/lib/libcmd/common/cat.c | 453 |
1 files changed, 311 insertions, 142 deletions
diff --git a/usr/src/lib/libcmd/common/cat.c b/usr/src/lib/libcmd/common/cat.c index 76af2f2765..e451998cc2 100644 --- a/usr/src/lib/libcmd/common/cat.c +++ b/usr/src/lib/libcmd/common/cat.c @@ -1,7 +1,7 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 1992-2008 AT&T Intellectual Property * +* Copyright (c) 1992-2009 AT&T Intellectual Property * * and is licensed under the * * Common Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -31,7 +31,7 @@ #include <fcntl.h> static const char usage[] = -"[-?\n@(#)$Id: cat (AT&T Research) 2007-07-17 $\n]" +"[-?\n@(#)$Id: cat (AT&T Research) 2009-03-31 $\n]" USAGE_LICENSE "[+NAME?cat - concatenate files]" "[+DESCRIPTION?\bcat\b copies each \afile\a in sequence to the standard" @@ -62,6 +62,7 @@ USAGE_LICENSE "[D:dos-output?Output files are opened in \atext\amode which inserts carriage" " returns in front of new-lines on some systems.]" "[E:show-ends?Causes a \b$\b to be inserted before each new-line.]" +"[R:regress?Regression test defaults: \b-v\b buffer size 4.]" "[S:silent?\bcat\b is silent about non-existent files.]" "[T:show-blank?Causes tabs to be copied as \b^I\b and formfeeds as \b^L\b.]" @@ -87,146 +88,306 @@ USAGE_LICENSE #define d_FLAG (1<<9) /* character types */ -#define T_ENDBUF 1 -#define T_CONTROL 2 -#define T_NEWLINE 3 -#define T_EIGHTBIT 4 -#define T_CNTL8BIT 5 +#define T_ERROR 1 +#define T_EOF 2 +#define T_ENDBUF 3 +#define T_NEWLINE 4 +#define T_CONTROL 5 +#define T_EIGHTBIT 6 +#define T_CNTL8BIT 7 #define printof(c) ((c)^0100) +typedef void* (*Reserve_f)(Sfio_t*, ssize_t, int); + +#ifndef sfvalue +#define sfvalue(f) ((f)->_val) +#endif + +static void* +regress(Sfio_t* sp, ssize_t n, int f) +{ + void* r; + + if (!(r = sfreserve(sp, 4, f))) + r = sfreserve(sp, n, f); + else if (sfvalue(sp) > 4) + sfvalue(sp) = 4; + return r; +} + /* * called for any special output processing */ static int -vcat(register char* states, Sfio_t *fdin, Sfio_t *fdout, int flags) +vcat(register char* states, Sfio_t* ip, Sfio_t* op, Reserve_f reserve, int flags) { register unsigned char* cp; - register unsigned char* cpold; + register unsigned char* pp; + unsigned char* cur; + unsigned char* end; + unsigned char* buf; + unsigned char* nxt; register int n; - register int m; - register int line = 1; - register unsigned char* endbuff; - unsigned char* inbuff; - int printdefer = (flags&(B_FLAG|N_FLAG)); - int lastchar; - int lastline; + register int line; + register int raw; + int last; + int c; + int m; + int any; + int header; unsigned char meta[4]; + unsigned char tmp[32]; meta[0] = 'M'; meta[1] = '-'; + last = -1; + *(cp = buf = end = tmp) = 0; + any = 0; + header = flags & (B_FLAG|N_FLAG); + line = 1; + states[0] = T_ENDBUF; + raw = !mbwide(); for (;;) { - /* read in a buffer full */ - if (!(inbuff = (unsigned char*)sfreserve(fdin, SF_UNBOUND, 0))) - return sfvalue(fdin) ? -1 : 0; - if ((n = sfvalue(fdin)) <= 0) - return n; - cp = inbuff; - lastchar = *(endbuff = cp + --n); - *endbuff = 0; - if (printdefer) + cur = cp; + if (raw) + while (!(n = states[*cp++])); + else + for (;;) + { + while (!(n = states[*cp++])); + if (n < T_CONTROL) + break; + if ((m = mbsize(pp = cp - 1)) > 1) + cp += m - 1; + else + { + if (m <= 0) + { + if (cur == pp) + { + if (last > 0) + { + *end = last; + last = -1; + c = end - pp + 1; + if ((m = mbsize(pp)) == c) + { + any = 1; + if (header) + { + header = 0; + sfprintf(op, "%6d\t", line); + } + sfwrite(op, cur, m); + *(cp = cur = end) = 0; + } + else + { + memcpy(tmp, pp, c); + if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0))) + { + states[0] = sfvalue(ip) ? T_ERROR : T_EOF; + *(cp = end = tmp + sizeof(tmp) - 1) = 0; + last = -1; + } + else if ((n = sfvalue(ip)) <= 0) + { + states[0] = n ? T_ERROR : T_EOF; + *(cp = end = tmp + sizeof(tmp) - 1) = 0; + last = -1; + } + else + { + cp = buf = nxt; + end = buf + n - 1; + last = *end; + *end = 0; + } + mb: + if ((n = end - cp + 1) >= (sizeof(tmp) - c)) + n = sizeof(tmp) - c - 1; + memcpy(tmp + c, cp, n); + if ((m = mbsize(tmp)) >= c) + { + any = 1; + if (header) + { + header = 0; + sfprintf(op, "%6d\t", line); + } + sfwrite(op, tmp, m); + cur = cp += m - c; + } + } + continue; + } + } + else + { + cp = pp + 1; + n = 0; + } + } + break; + } + } + c = *--cp; + if ((m = cp - cur) || n >= T_CONTROL) { - if (states[*cp]!=T_NEWLINE || !(flags&B_FLAG)) - sfprintf(fdout,"%6d\t",line); - printdefer = 0; + flush: + any = 1; + if (header) + { + header = 0; + sfprintf(op, "%6d\t", line); + } + if (m) + sfwrite(op, cur, m); } - while (endbuff) + special: + switch (n) { - cpold = cp; - /* skip over printable characters */ - if (mbwide()) - while ((n = (m = mbsize(cp)) < 2 ? states[*cp++] : (cp += m, states['a'])) == 0); + case T_ERROR: + if (cp != end) + { + n = T_CONTROL; + goto flush; + } + return -1; + case T_EOF: + if (cp != end) + { + n = T_CONTROL; + goto flush; + } + return 0; + case T_ENDBUF: + if (cp != end) + { + n = T_CONTROL; + goto flush; + } + c = last; + if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0))) + { + *(cp = end = tmp) = 0; + states[0] = sfvalue(ip) ? T_ERROR : T_EOF; + last = -1; + } + else if ((m = sfvalue(ip)) <= 0) + { + *(cp = end = tmp) = 0; + states[0] = m ? T_ERROR : T_EOF; + last = -1; + } else - while ((n = states[*cp++]) == 0); - if (n==T_ENDBUF) { - if (cp>endbuff) + buf = nxt; + end = buf + m - 1; + last = *end; + *end = 0; + cp = buf; + } + if (c >= 0) + { + if (!(n = states[c])) { - if (!(n = states[lastchar])) - { - *endbuff = lastchar; - cp++; - } - else - { - if (--cp > cpold) - sfwrite(fdout,(char*)cpold,cp-cpold); - if (endbuff==inbuff) - *++endbuff = 0; - cp = cpold = endbuff; - cp[-1] = lastchar; - if (n==T_ENDBUF) - n = T_CONTROL; - - } - endbuff = 0; + *(cur = tmp) = c; + m = 1; + goto flush; } - else n = T_CONTROL; + if (raw || n < T_CONTROL) + { + cp--; + goto special; + } + tmp[0] = c; + c = 1; + goto mb; } - if (--cp>cpold) - sfwrite(fdout,(char*)cpold,cp-cpold); - switch(n) + break; + case T_CONTROL: + do { - case T_CNTL8BIT: - meta[2] = '^'; - do - { - n = (*cp++)&~0200; - meta[3] = printof(n); - sfwrite(fdout,(char*)meta,4); - } - while ((n=states[*cp])==T_CNTL8BIT); - break; - case T_EIGHTBIT: - do - { - meta[2] = (*cp++)&~0200; - sfwrite(fdout,(char*)meta,3); - } - while ((n=states[*cp])==T_EIGHTBIT); - break; - case T_CONTROL: - do + sfputc(op, '^'); + sfputc(op, printof(c)); + } while (states[c = *++cp] == T_CONTROL); + break; + case T_CNTL8BIT: + meta[2] = '^'; + do + { + n = c & ~0200; + meta[3] = printof(n); + sfwrite(op, (char*)meta, 4); + } while (states[c = *++cp] == T_CNTL8BIT && raw); + break; + case T_EIGHTBIT: + do + { + meta[2] = c & ~0200; + sfwrite(op, (char*)meta, 3); + } while (states[c = *++cp] == T_EIGHTBIT && raw); + break; + case T_NEWLINE: + if (header && !(flags & B_FLAG)) + sfprintf(op, "%6d\t", line); + if (flags & E_FLAG) + sfputc(op, '$'); + sfputc(op, '\n'); + if (!header || !(flags & B_FLAG)) + line++; + header = !(flags & S_FLAG); + for (;;) + { + if ((n = states[*++cp]) == T_ENDBUF) + { + if (cp != end || last != '\n') + break; + if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0))) { - n = *cp++; - sfputc(fdout,'^'); - sfputc(fdout,printof(n)); + states[0] = sfvalue(ip) ? T_ERROR : T_EOF; + cp = end = tmp; + *cp-- = 0; + last = -1; } - while ((n=states[*cp])==T_CONTROL); - break; - case T_NEWLINE: - lastline = line; - if (flags&S_FLAG) + else if ((n = sfvalue(ip)) <= 0) { - while (states[*++cp]==T_NEWLINE) - line++; - cp--; + states[0] = n ? T_ERROR : T_EOF; + cp = end = tmp; + *cp-- = 0; + last = -1; } - do + else { - cp++; - if (flags&E_FLAG) - sfputc(fdout,'$'); - sfputc(fdout,'\n'); - if(line > lastline) - { - if (flags&E_FLAG) - sfputc(fdout,'$'); - sfputc(fdout,'\n'); - } - if (!(flags&(N_FLAG|B_FLAG))) - continue; - line++; - if (cp < endbuff) - sfprintf(fdout,"%6d\t",line); - else printdefer = 1; + buf = nxt; + end = buf + n - 1; + last = *end; + *end = 0; + cp = buf - 1; } - while (states[*cp]==T_NEWLINE); + } + else if (n != T_NEWLINE) break; + if (!(flags & S_FLAG) || any || header) + { + any = 0; + header = 0; + if ((flags & (B_FLAG|N_FLAG)) == N_FLAG) + sfprintf(op, "%6d\t", line); + if (flags & E_FLAG) + sfputc(op, '$'); + sfputc(op, '\n'); + } + if (!(flags & B_FLAG)) + line++; } + header = flags & (B_FLAG|N_FLAG); + break; } } } @@ -239,60 +400,65 @@ b_cat(int argc, char** argv, void* context) register char* cp; register Sfio_t* fp; char* mode; + Reserve_f reserve = sfreserve; int att; - int dovcat=0; + int dovcat = 0; char states[UCHAR_MAX+1]; - NoP(argc); cmdinit(argc, argv, context, ERROR_CATALOG, 0); + setlocale(LC_ALL, ""); att = !strcmp(astconf("UNIVERSE", NiL, NiL), "att"); mode = "r"; for (;;) { + n = 0; switch (optget(argv, usage)) { case 'A': - flags |= T_FLAG|E_FLAG|V_FLAG; - continue; + n = T_FLAG|E_FLAG|V_FLAG; + break; case 'B': - flags |= S_FLAG; - continue; + n = S_FLAG; + break; case 'b': - flags |= B_FLAG; + n = B_FLAG; + break; + case 'd': + mode = opt_info.num ? "rt" : "r"; continue; + case 'D': + n = d_FLAG; + break; case 'E': - flags |= E_FLAG; - continue; + n = E_FLAG; + break; case 'e': - flags |= E_FLAG|V_FLAG; - continue; + n = E_FLAG|V_FLAG; + break; case 'n': - flags |= N_FLAG; + n = N_FLAG; + break; + case 'R': + reserve = opt_info.num ? regress : sfreserve; continue; case 's': - flags |= att ? F_FLAG : S_FLAG; - continue; + n = att ? F_FLAG : S_FLAG; + break; case 'S': - flags |= F_FLAG; - continue; + n = F_FLAG; + break; case 'T': - flags |= T_FLAG; - continue; + n = T_FLAG; + break; case 't': - flags |= T_FLAG|V_FLAG; - continue; + n = T_FLAG|V_FLAG; + break; case 'u': - flags |= U_FLAG; - continue; + n = U_FLAG; + break; case 'v': - flags |= V_FLAG; - continue; - case 'd': - mode = "rt"; - continue; - case 'D': - flags |= d_FLAG; - continue; + n = V_FLAG; + break; case ':': error(2, "%s", opt_info.arg); break; @@ -300,7 +466,12 @@ b_cat(int argc, char** argv, void* context) error(ERROR_usage(2), "%s", opt_info.arg); break; } - break; + if (!n) + break; + if (opt_info.num) + flags |= n; + else + flags &= ~n; } argv += opt_info.index; if (error_info.errors) @@ -340,15 +511,13 @@ b_cat(int argc, char** argv, void* context) states['\n'] = T_NEWLINE; dovcat = 1; } - if (flags&B_FLAG) - flags |= S_FLAG; if (flags&d_FLAG) sfopen(sfstdout, NiL, "wt"); if (cp = *argv) argv++; do { - if (!cp || streq(cp,"-")) + if (!cp || streq(cp, "-")) { fp = sfstdin; if (flags&D_FLAG) @@ -364,7 +533,7 @@ b_cat(int argc, char** argv, void* context) if (flags&U_FLAG) sfsetbuf(fp, (void*)fp, -1); if (dovcat) - n = vcat(states, fp, sfstdout, flags); + n = vcat(states, fp, sfstdout, reserve, flags); else if (sfmove(fp, sfstdout, SF_UNBOUND, -1) >= 0 && sfeof(fp)) n = 0; else |