/* vi:ts=4:sw=4 * * JCAT - Japanized CAT * * Code Contributions By: Atsushi Nakamura ann@mrit.mei.co.jp * */ #define EXTERN #include "vim.h" #ifdef JP #include "jp.h" #endif #include "globals.h" #include "proto.h" #ifndef M_XENIX # include #endif #include #ifndef MSDOS # ifdef SYSV_UNIX # if defined(M_XENIX) || defined(SCO) || defined(UNICOS) || defined(AIX31) # include # else # if !defined(AUX3) # include # endif # endif # else /* SYSV_UNIX */ # include # endif /* !SYSV_UNIX */ #endif /* !MSDOS */ #if defined(FD_ZERO) && defined(SYSV_UNIX) # undef FD_ZERO #endif #undef free #ifdef IOSIZE # undef IOSIZE #endif /* #define IOSIZE 20 #define LINESIZE 10 */ #define IOSIZE 4096 #define LINESIZE 4096 static void usage(); void emsg(msg) char *msg; { fprintf(stderr, "%s\n", msg); } #ifndef MSDOS # define T_FILE 2 static int text = FALSE; #endif static int o_lnum = FALSE; /* -n */ static int o_lnume = FALSE; /* -b */ static int o_vis = FALSE; /* -v */ static int o_vist = FALSE; /* -t */ static int o_visl = FALSE; /* -e */ static int o_smel = FALSE; /* -s */ #ifndef MSDOS static int o_text = T_FILE; /* -T, -B */ #endif static int o_ubf = FALSE; /* -u */ static int o_serr = FALSE; /* -Q */ static int o_scode = FALSE; /* -C */ static void usage() { #ifdef JP fprintf(stderr, "Jcat/%s by ann@mrit.mei.co.jp\n", JpVersion); #else fprintf(stderr, "Non Japanized Jcat by ann@mrit.mei.co.jp\n"); #endif fprintf(stderr, "Usage: jcat [ -benstuv ] [filename ...]\n"); fprintf(stderr, " -n number the lines.\n"); fprintf(stderr, " -b number the lines omitting blank line.\n"); fprintf(stderr, " -v display non printable characters.\n"); fprintf(stderr, " -t display TAB as ^I and LF as ^L with -v.\n"); fprintf(stderr, " -e display $ at the end of line as with -v.\n"); fprintf(stderr, " -s suppress multiple blank lines.\n"); fprintf(stderr, " -u unbuffered.\n"); fprintf(stderr, "\n"); #ifndef MSDOS fprintf(stderr, " -T display NEWLINE as CR-LF(MS-DOS text mode).\n"); fprintf(stderr, " -B display NEWLINE as LF(UNIX text or MS-DOS binary mode).\n"); #endif fprintf(stderr, " -Q suppress error messages.\n"); #ifdef JP fprintf(stderr, " -C print kanji code.\n"); fprintf(stderr, " -N -J -E -S -X \n"); fprintf(stderr, " kanji code for output.\n"); fprintf(stderr, " -. -, kanji code for input.\n"); #endif fprintf(stderr, " Use - as a filename to read from standard input.\n"); fprintf(stderr, "\n"); #ifdef JP fprintf(stderr, "Environment JMASK specifies default Kanji code.\n"); #endif fprintf(stderr, "Do not concatenate binary files by this program.\n"); exit(1); } char jread; char jdisp; void main(argc, argv) int argc; char **argv; { #ifdef JP static char jmask[4] = JP; #endif int i; char *cp; ++argv; /* * Process the command line arguments */ #ifdef JP if ((cp = (char *)getenv("JMASK")) != NULL) strncpy(jmask, cp, 4); if (jmask[0] && !strchr("NJESX,.", jmask[0])) { fprintf(stderr, "Unknown Kanji code %c for reading.\n", jmask[0]); return; } if (jmask[1] && !strchr("NJESX", jmask[1])) { fprintf(stderr, "Unknown Kanji code %c for writing.\n", jmask[1]); return; } jread = jmask[0]; jdisp = jmask[1]; #else jread = jdisp = JP_NONE; #endif if (argc > 1 && argv[0][0] == '-' && argv[0][1] !=NUL) { char *cp; for(cp = argv[0] + 1; *cp; cp++) { switch(*cp) { case 'n': o_lnum = TRUE; break; case 'b': o_lnume = TRUE; break; case 'v': o_vis = TRUE; break; case 't': o_vist = TRUE; break; case 'e': o_visl = TRUE; break; case 's': o_smel = TRUE; break; case 'u': o_ubf = TRUE; break; case 'Q': o_serr = TRUE; break; #ifndef MSDOS case 'T': o_text = TRUE; break; case 'B': o_text = FALSE; break; #endif #ifdef JP case 'C': o_scode = TRUE; break; case 'N': case 'J': case 'E': case 'S': case 'X': jdisp = *cp; break; case 'x': if (* ++cp == NUL) { cp --; fprintf(stderr, "Next of 'x' should be one of NJESX., \n"); usage(); break; } case ',': case '.': jread = *cp; break; #endif default: fprintf(stderr, "Unknown option '%c'\n", *cp); usage(); break; } } ++ argv; -- argc; } #ifndef MSDOS if (o_text != T_FILE) text = o_text; #endif #if !defined(UNIX) && !defined(MSDOS) ExpandWildCards(argc - 1, argv, &numfiles, &files, TRUE, TRUE); if (numfiles != 0) files_exp = TRUE; #else files = argv; numfiles = argc - 1; #endif /* * execute cat for each file */ { int do_cat(); int lnum; lnum = 0; if (numfiles == 0) do_cat(lnum, 0, NULL); else for(i = 0; i < numfiles; i++) { int fd; #ifdef AMIGA fname_case(files[i]); /* set correct case for file name */ #endif if (!strcmp(files[i], "-")) fd = 0; #ifdef UNIX else if (o_ubf) # ifdef O_NDELAY fd = open(files[i], O_RDONLY | O_NDELAY); # else fd = open(files[i], O_RDONLY | O_NONBLOCK); # endif #endif else fd = open(files[i], O_RDONLY); if (fd >= 0) { lnum = do_cat(lnum, fd, fd == 0 ? NULL: files[i]); close(fd); } else if (!o_serr) fprintf(stderr, "jcat: %s cannot open\n", files[i]); } } } static char round[5], *rp; static char Rbuf[IOSIZE * 2], *Rp, *Rend; static int kanji; static int reof; static void j_init() { reof = kanji = FALSE; rp = round; #ifdef JP reset_jcount(); #endif Rp = Rend = Rbuf; } /* * j_readln(line, size) returns the number of char. transferred into 'line' * note: line is not NUL terminated. * return -1: EOF reached * return -2: Error */ static int j_readln(fd, line, size) int fd; char *line; int size; { int len; char c; len = 0; retry: while (Rp != Rend) { c = *line ++ = *Rp ++; len ++; #ifdef JP if (IsKanji(c)) { *line ++ = *Rp ++; len ++; } else #endif if (c == '\r' && *Rp == '\n') { #ifndef MSDOS if (o_text == T_FILE) o_text = text = TRUE; #endif /* suppress CR for MS-DOS text */ c = *(line - 1) = *Rp ++; } #ifndef MSDOS else if (c == '\n' && o_text == T_FILE) o_text = text = FALSE; #endif if (c == '\n' || len >= size - 1) return len; } if (o_ubf && len) return len; if (reof) { if (rp != round) { memmove(Rbuf, round, rp - round); rp = round; Rp = Rbuf; Rend = Rbuf + (rp - round); goto retry; } else if (len) return len; else return -1; } #ifdef UNIX /* * wait until read data is ready if unbufferd file is opend. */ if (o_ubf) # ifndef FD_ZERO { struct pollfd fds[1]; fds[0].fd = fd; fds[0].events = POLLIN; if (poll(fds, 1, -1) == -1) return -2; } # else { extern int select(); fd_set fds; FD_ZERO(&fds); FD_SET(fd, &fds); if (select(32, &fds, NULL, NULL, NULL) <= 0) return -2; if (!FD_ISSET(fd, &fds)) return -2; } # endif #endif /* reload Rbuf */ { static char cbuf[IOSIZE]; int clen; int ofst; if (rp != round) /* flush round buffer */ { memmove(cbuf, round, ofst = rp - round); rp = round; } else ofst = 0; clen = read(fd, cbuf + ofst, IOSIZE - ofst); if (clen < 0) return -2; reof = (clen == 0); clen += ofst; Rend = Rp = Rbuf; #ifdef JP Rend += kanjiconvsfrom(cbuf, clen, Rbuf, IOSIZE * 2, round, jread, &kanji); #endif rp = round + strlen(round); goto retry; } } int do_cat(lnum, fd, fname) int lnum; int fd; char *fname; { static char Lbuf[LINESIZE]; static char Cbuf[LINESIZE * 2 + 2]; char *Lp, *Cp; int len; int linetop; int lastempty; char *prline; char jcode; #ifdef JP j_init(); #endif linetop = TRUE; lastempty = FALSE; lnum = 0; while((len = j_readln(fd, Lbuf, LINESIZE)) != -1) { int isempty; int tailnl; char *cp; if (len == -2) { fprintf(stderr, "jcat: read error(%s).", fname ? fname: "standard input"); exit(-1); } isempty = linetop && Lbuf[0] == '\n'; if (linetop) { lnum++; if (isempty && o_lnume) lnum--; else if (lastempty && isempty && o_smel) continue; else if (o_lnum || o_lnume) { char linehead[20]; sprintf(linehead, "%6d ", lnum); write(1, linehead, 6 + 2); } } lastempty = isempty; linetop = FALSE; /* * Generate print string. */ tailnl = FALSE; for(Lp = Lbuf, Cp = Cbuf; len; Lp++, Cp++, len--) { char c; c = *Lp; #ifdef JP if (IsKanji(c)) { if (o_vis && c == '\377') { *Cp ++ = '~'; *Cp = '?'; } else if (o_vis && (c & 0xe0) == 0) { *Cp ++ = '~'; *Cp = (c & 0x1f) + '@'; } else { *Cp ++ = c; *Cp = * ++Lp; len --; } } else #endif { if (c == '\n') { if (o_vis && o_visl) *Cp ++ = '$'; *Cp = c; linetop = TRUE; tailnl = TRUE; } else if (!o_vis) *Cp = (c == NUL) ? '\n' : c; else if (!o_vist && (c == TAB || c == Ctrl('L'))) *Cp = c; else if ((c & 0xe0) == 0) { *Cp ++ = '^'; *Cp = c + '@'; } else if (c == '\177') { *Cp ++ = '^'; *Cp = '?'; } else *Cp = c; } } *Cp = NUL; #ifdef JP prline = kanjiconvsto(Cbuf, jdisp); #else prline = Cbuf; #endif { int crlf; crlf = FALSE; for(cp = prline, len = 0; *cp; cp++, len++) if (*cp == '\n') { if (tailnl && *(cp + 1) == NUL) { #ifndef MSDOS if (!text) continue; #endif crlf = TRUE; break; } *cp = NUL; } if (write(1, prline, len) < 0 ) exit(-1); if (crlf) if (write(1, "\r\n", 2) < 0 ) exit(-1); } if (prline != Cbuf) free(prline); } #ifdef JP jcode = judge_jcode(jread); if (!o_serr) { int jisx0201r; extern int num_jis0201r(); if (jread == JP_ANY && jcode == JP_SJIS) { if (fname) fprintf(stderr, "%s: ", fname); fprintf(stderr, "EUC SJIS conflict: "); fprintf(stderr, "Use ',' option to read SJIS file.\n"); } if (jread == JP_SANY && jcode == JP_EUC) { if (fname) fprintf(stderr, "%s: ", fname); fprintf(stderr, "EUC SJIS conflict: "); fprintf(stderr, "Use '.' option to read EUC file.\n"); } jisx0201r = num_jis0201r(); if (jisx0201r) { if (fname) fprintf(stderr, "%s: ", fname); fprintf(stderr, "%d Hankaku Kana -> Zenkaku Katakana\n", jisx0201r); } } if (o_scode) { if (fname) printf("%s: ", fname); printf("%c\n", jcode); } #endif return lnum; } void getout(r) int r; { fprintf(stderr, "\n"); exit(r); }