/* 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 <sys/types.h>
#endif
#include <fcntl.h>
#ifndef MSDOS
# ifdef SYSV_UNIX
# if defined(M_XENIX) || defined(SCO) || defined(UNICOS) || defined(AIX31)
# include <sys/select.h>
# else
# if !defined(AUX3)
# include <poll.h>
# endif
# endif
# else /* SYSV_UNIX */
# include <sys/time.h>
# 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);
}
syntax highlighted by Code2HTML, v. 0.9.1